Skip to content

Commit

Permalink
Assimilate thenables only if necessary--ie if the promise assimilatin…
Browse files Browse the repository at this point in the history
…g them is observed
  • Loading branch information
briancavalier committed Mar 8, 2014
1 parent a249229 commit a0f2030
Showing 1 changed file with 30 additions and 28 deletions.
58 changes: 30 additions & 28 deletions lib/makePromise.js
Expand Up @@ -425,16 +425,43 @@ define(function() {
* Handler that wraps an untrusted thenable and assimilates it in a future stack
* @private
* @param {function} then
* @param {{then: function}} x
* @param {{then: function}} thenable
* @constructor
*/
function ThenableHandler(then, x) {
function ThenableHandler(then, thenable) {
DeferredHandler.call(this);
tasks.enqueue(new AssimilateTask(then, x, this));
this.assimilated = false;
this.untrustedThen = then;
this.thenable = thenable;
}

ThenableHandler.prototype = Object.create(DeferredHandler.prototype);

ThenableHandler.prototype.when = function(resolve, notify, t, receiver, f, r, u) {
if(!this.assimilated) {
this.assimilated = true;
this._assimilate();
}
DeferredHandler.prototype.when.call(this, resolve, notify, t, receiver, f, r, u);
};

ThenableHandler.prototype._assimilate = function() {
var h = this;
this._try(this.untrustedThen, this.thenable, _resolve, _reject, _notify);

function _resolve(x) { h.resolve(x); }
function _reject(x) { h.reject(x); }
function _notify(x) { h.notify(x); }
};

ThenableHandler.prototype._try = function(then, thenable, resolve, reject, notify) {
try {
then.call(thenable, resolve, reject, notify);
} catch (e) {
reject(e);
}
};

/**
* Handler for a fulfilled promise
* @private
Expand Down Expand Up @@ -535,31 +562,6 @@ define(function() {
this.handler.when(this.a, this.b, this.c, this.d, this.e, this.f, this.g);
};

/**
* Extract the value of an untrusted thenable by calling
* its then() method in a future stack
* @private
* @constructor
*/
function AssimilateTask(then, thenable, handler) {
this.untrustedThen = then;
this.thenable = thenable;
this.handler = handler;
}

AssimilateTask.prototype.run = function() {
var h = this.handler;
try {
this.untrustedThen.call(this.thenable,
function(x) { h.resolve(x); },
function(x) { h.reject(x); },
function(x) { h.notify(x); }
);
} catch (e) {
h.reject(e);
}
};

/**
* Run a queue of progress handlers
* @private
Expand Down

0 comments on commit a0f2030

Please sign in to comment.