Skip to content

Commit

Permalink
Collapse promise state value; combine with length field.
Browse files Browse the repository at this point in the history
This reduces memory usage, and also ensures the type of all the
handlers is consistently `Function`.
  • Loading branch information
cscott committed Dec 8, 2015
1 parent eb1f4ea commit dd0c7e4
Showing 1 changed file with 21 additions and 18 deletions.
39 changes: 21 additions & 18 deletions lib/promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,11 @@ var enqueue = useAsap ? require('asap/raw') : IsCallable(global.setImmediate) ?
function(task) { setTimeout(task, 0); }); // Fallback

// Constants for Promise implementation
var PROMISE_IDENTITY = 1;
var PROMISE_THROWER = 2;
var PROMISE_PENDING = 3;
var PROMISE_FULFILLED = 4;
var PROMISE_REJECTED = 5;
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 promiseReactionJob = function(reaction, argument) {
var promiseCapability = reaction.capabilities;
Expand Down Expand Up @@ -196,33 +196,35 @@ var triggerPromiseReactions = function(reactions, argument) {
};

var fulfillPromise = function(promise, value) {
/* jshint bitwise: false */
var reactions = [];
if (promise._promise_length > 0) {
var length = promise._promise_state >>> 2;
if (length > 0) {
reactions.push(promise._promise_fulfillReactions0);
for (var i = 1; i < promise._promise_length; i++) {
for (var i = 1; i < length; i++) {
reactions.push(promise[2 * (i - 1)]);
}
}
promise._promise_result = value;
promise._promise_fulfillReactions0 = void 0;
promise._promise_rejectReactions0 = void 0;
promise._promise_length = 0;
promise._promise_state = PROMISE_FULFILLED;
triggerPromiseReactions(reactions, value);
};

var rejectPromise = function(promise, reason) {
/* jshint bitwise: false */
var reactions = [];
if (promise._promise_length > 0) {
var length = promise._promise_state >>> 2;
if (length > 0) {
reactions.push(promise._promise_rejectReactions0);
for (var i = 1; i < promise._promise_length; i++) {
for (var i = 1; i < length; i++) {
reactions.push(promise[1 + 2 * (i - 1)]);
}
}
promise._promise_result = reason;
promise._promise_fulfillReactions0 = void 0;
promise._promise_rejectReactions0 = void 0;
promise._promise_length = 0;
promise._promise_state = PROMISE_REJECTED;
triggerPromiseReactions(reactions, reason);
};
Expand Down Expand Up @@ -272,7 +274,7 @@ var Promise = function Promise(resolver) {
if (!(this instanceof Promise)) {
throw new TypeError('Constructor Promise requires "new"');
}
if (this && this._promise_state) {
if (this && typeof this._promise_state !== 'undefined') {
throw new TypeError('Bad construction');
}
// see https://bugs.ecmascript.org/show_bug.cgi?id=2482
Expand All @@ -286,7 +288,6 @@ var Promise = function Promise(resolver) {
// on the object's element array to avoid unnecessary indirection.
this._promise_result = void 0;
this._promise_state = PROMISE_PENDING;
this._promise_length = 0;
this._promise_fulfillReactions0 = void 0;
this._promise_rejectReactions0 = void 0;
var resolvingFunctions = createResolvingFunctions(this);
Expand Down Expand Up @@ -333,6 +334,7 @@ defineProperties(Promise$prototype, {
},

then: function then(onFulfilled, onRejected) {
/* jshint bitwise: false */
var promise = this;
if (!IsPromise(promise)) { throw new TypeError('not a promise'); }
var C = SpeciesConstructor(promise, Promise);
Expand All @@ -352,18 +354,19 @@ defineProperties(Promise$prototype, {
capabilities: resultCapability,
handler: onRejected,
};
var value;
switch (promise._promise_state) {
var value, length;
switch (promise._promise_state & 3) {
case PROMISE_PENDING:
if (promise._promise_length === 0) {
length = promise._promise_state >>> 2;
if (length === 0) {
promise._promise_fulfillReactions0 = fulfillReaction;
promise._promise_rejectReactions0 = rejectReaction;
} else {
var i = 2 * (promise._promise_length - 1);
var i = 2 * (length - 1);
promise[i] = fulfillReaction;
promise[i + 1] = rejectReaction;
}
promise._promise_length++;
promise._promise_state += (1 << 2);
break;
case PROMISE_FULFILLED:
value = promise._promise_result;
Expand Down

0 comments on commit dd0c7e4

Please sign in to comment.