diff --git a/doc/api.txt b/doc/api.txt index 5d09d9ac95..688bf68047 100644 --- a/doc/api.txt +++ b/doc/api.txt @@ -290,9 +290,11 @@ emit anymore events. +promise.addCallback(listener)+ :: Adds a listener for the +"success"+ event. Returns the same promise object. +The listener is executed right away if the promise has already fired. +promise.addErrback(listener)+ :: Adds a listener for the +"error"+ event. Returns the same promise object. +The listener is executed right away if the promise has already fired. +promise.emitSuccess(arg1, arg2, ...)+ :: If you created the promise (by doing +new events.Promise()+) then call diff --git a/src/node.js b/src/node.js index 9306cf81cf..6fc0ea4402 100644 --- a/src/node.js +++ b/src/node.js @@ -232,6 +232,7 @@ var eventsModule = createInternalModule('events', function (exports) { exports.EventEmitter.call(); this._blocking = false; this.hasFired = false; + this._values = undefined; }; process.inherits(exports.Promise, exports.EventEmitter); @@ -277,24 +278,34 @@ var eventsModule = createInternalModule('events', function (exports) { exports.Promise.prototype.emitSuccess = function() { if (this.hasFired) return; this.hasFired = true; - Array.prototype.unshift.call(arguments, 'success') - this.emit.apply(this, arguments); + + this._values = Array.prototype.slice.call(arguments); + this.emit.apply(this, ['success'].concat(this._values)); }; exports.Promise.prototype.emitError = function() { if (this.hasFired) return; this.hasFired = true; - Array.prototype.unshift.call(arguments, 'error') - this.emit.apply(this, arguments); + + this._values = Array.prototype.slice.call(arguments); + this.emit.apply(this, ['error'].concat(this._values)); }; exports.Promise.prototype.addCallback = function (listener) { - this.addListener("success", listener); + if (!this.hasFired) { + return this.addListener("success", listener); + } + + listener.apply(this, this._values); return this; }; exports.Promise.prototype.addErrback = function (listener) { - this.addListener("error", listener); + if (!this.hasFired) { + return this.addListener("error", listener); + } + + listener.apply(this, this._values); return this; }; diff --git a/test/mjsunit/test-promise.js b/test/mjsunit/test-promise.js new file mode 100644 index 0000000000..e042030c4f --- /dev/null +++ b/test/mjsunit/test-promise.js @@ -0,0 +1,50 @@ +process.mixin(require('./common')); +var + Promise = require('events').Promise, + + TEST_VALUE = {some: 'object'}, + + expectedCallbacks = { + a1: 1, + a2: 1, + b1: 1, + b2: 1, + }; + +// Test regular & late callback binding +var a = new Promise(); +a.addCallback(function(value) { + assert.equal(TEST_VALUE, value); + expectedCallbacks.a1--; +}); +a.emitSuccess(TEST_VALUE); + +a.addCallback(function(value) { + assert.equal(TEST_VALUE, value); + expectedCallbacks.a2--; +}); + +// Test regular & late errback binding +var b = new Promise(); +b.addErrback(function(value) { + assert.equal(TEST_VALUE, value); + expectedCallbacks.b1--; +}); +b.emitError(TEST_VALUE); + +b.addErrback(function(value) { + assert.equal(TEST_VALUE, value); + expectedCallbacks.b2--; +}); + +process.addListener('exit', function() { + for (var name in expectedCallbacks) { + var count = expectedCallbacks[name]; + + assert.equal( + 0, + count, + 'Callback '+name+' fire count off by: '+count + ); + } +}); \ No newline at end of file