Skip to content

Commit

Permalink
Inline createResolvingFunctions().
Browse files Browse the repository at this point in the history
This avoids creating a result object and saves some memory for a boolean
in the non-chaining case.
  • Loading branch information
cscott committed Dec 8, 2015
1 parent 93ff998 commit ed96b47
Showing 1 changed file with 42 additions and 30 deletions.
72 changes: 42 additions & 30 deletions lib/promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ var enqueue = useAsap ? require('asap/raw') : IsCallable(global.setImmediate) ?
var PROMISE_IDENTITY = (function(v) { return v; });
var PROMISE_THROWER = (function(t) { throw t; });
var PROMISE_PENDING = 0;
var PROMISE_FULFILLED = 1;
var PROMISE_REJECTED = 2;
var PROMISE_RESOLVING = 1; // PROMISE_PENDING combined with alreadyResolved
var PROMISE_FULFILLED = 2;
var PROMISE_REJECTED = 3;

var promiseReactionJob = function(handler, promiseCapability, argument) {
var handlerResult, resolve, reject;
Expand Down Expand Up @@ -257,41 +258,38 @@ var rejectPromise = function(promise, reason) {
promise._promise_state = PROMISE_REJECTED;
};

var createResolvingFunctions = function(promise) {
var resolvePromise = function(promise, resolution) {
if (resolution === promise) {
return rejectPromise(promise, new TypeError('Self resolution'));
}
if (!TypeIsObject(resolution)) {
return fulfillPromise(promise, resolution);
}
var then = tryCatch1(function(r) { return r.then; }, resolution);
if (then === errorObj) {
return rejectPromise(promise, then.e);
}
if (!IsCallable(then)) {
return fulfillPromise(promise, resolution);
}
enqueue(function() {
promiseResolveThenableJob(promise, resolution, then);
});
};

var promiseResolveThenableJob = function(promise, thenable, then) {
// Inlined copy of createResolvingFunctions(promise)
var alreadyResolved = false;
var resolve = function(resolution) {
var then;
if (alreadyResolved) { return; }
alreadyResolved = true;
if (resolution === promise) {
return rejectPromise(promise, new TypeError('Self resolution'));
}
if (!TypeIsObject(resolution)) {
return fulfillPromise(promise, resolution);
}
then = tryCatch1(function(r) { return r.then; }, resolution);
if (then === errorObj) {
return rejectPromise(promise, then.e);
}
if (!IsCallable(then)) {
return fulfillPromise(promise, resolution);
}
enqueue(function() {
promiseResolveThenableJob(promise, resolution, then);
});
resolvePromise(promise, resolution);
};
var reject = function(reason) {
if (alreadyResolved) { return; }
alreadyResolved = true;
return rejectPromise(promise, reason);
};
return { resolve: resolve, reject: reject };
};

var promiseResolveThenableJob = function(promise, thenable, then) {
var resolvingFunctions = createResolvingFunctions(promise);
var resolve = resolvingFunctions.resolve;
var reject = resolvingFunctions.reject;
var value = tryCatch2r(then, thenable, resolve, reject);
if (value === errorObj) {
reject(value.e);
Expand Down Expand Up @@ -319,9 +317,22 @@ var Promise = function Promise(resolver) {
this._promise_fulfillReactions0 = void 0;
this._promise_rejectReactions0 = void 0;
this._promise_reactionCapability0 = void 0;
var resolvingFunctions = createResolvingFunctions(this);
var reject = resolvingFunctions.reject;
var value = tryCatch2(resolver, resolvingFunctions.resolve, reject);
// Inlined copy of createResolvingFunctions(this), using _promise_state
// to track the `alreadyResolved` boolean.
var promise = this;
var resolve = function(resolution) {
/* jshint bitwise: false */
if ((promise._promise_state & 3) !== PROMISE_PENDING) { return; }
promise._promise_state++; // Sets state to PROMISE_RESOLVING
resolvePromise(promise, resolution);
};
var reject = function(reason) {
/* jshint bitwise: false */
if ((promise._promise_state & 3) !== PROMISE_PENDING) { return; }
promise._promise_state++; // Sets state to PROMISE_RESOLVING
rejectPromise(promise, reason);
};
var value = tryCatch2(resolver, resolve, reject);
if (value === errorObj) {
reject(value.e);
}
Expand Down Expand Up @@ -379,6 +390,7 @@ defineProperties(Promise$prototype, {
var length;
switch (promise._promise_state & 3) {
case PROMISE_PENDING:
case PROMISE_RESOLVING:
length = promise._promise_state >>> 2;
if (length === 0) {
promise._promise_fulfillReactions0 = onFulfilled;
Expand Down

0 comments on commit ed96b47

Please sign in to comment.