Skip to content

Commit

Permalink
Give up on weak maps
Browse files Browse the repository at this point in the history
No more guarantees.

Ten times faster.
  • Loading branch information
kriskowal committed Nov 2, 2014
1 parent a1293fa commit 254347a
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 36 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
},
"main": "q.js",
"dependencies": {
"asap": "^1.0.0",
"collections": ">=2.0.1 <3.0.0"
"asap": "^2.0.0",
"weak-map": "^1.0.5"
},
"devDependencies": {
"jshint": "^2.4.4",
Expand Down
50 changes: 18 additions & 32 deletions q.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ try {
var qStartingLine = captureLine();
var qFileName;

require("collections/shim");
var WeakMap = require("collections/weak-map");
var Iterator = require("collections/iterator");
var WeakMap = require("weak-map");
var asap = require("asap");
var iterate = require("./iterate");

var typeOfObject = "object";
function isObject(value) {
return value === Object(value);
return value !== null && typeof value === typeOfObject;
}

// long stack traces
Expand All @@ -64,7 +64,7 @@ function makeStackTraceLong(error, promise) {
error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
) {
var stacks = [];
for (var p = promise; !!p && handlers.get(p); p = handlers.get(p).became) {
for (var p = promise; p instanceof Promise && p._handler; p = p._handler.became) {
if (p.stack) {
stacks.unshift(p.stack);
}
Expand Down Expand Up @@ -179,33 +179,22 @@ function deprecate(callback, name, alternative) {

// end of long stack traces

var handlers = new WeakMap();

// When a deferred promise is forwarded to another promise, the old handler
// becomes the new handler and all messages past and present flow to the next
// handler.
function Q_getHandler(promise) {
var handler = handlers.get(promise);
if (!handler || !handler.became) {
return handler;
var handler = promise._handler;
while (handler && handler.became) {
handler = handler.became;
}
handler = follow(handler);
handlers.set(promise, handler);
promise._handler = handler;
return handler;
}

function follow(handler) {
if (!handler.became) {
return handler;
} else {
handler.became = follow(handler.became);
return handler.became;
}
}

var theViciousCycleError = new Error("Can't resolve a promise with itself");
var theViciousCycleRejection = Q_reject(theViciousCycleError);
var theViciousCycle = Q_getHandler(theViciousCycleRejection);

var thenables = new WeakMap();

/**
* Coerces a value to a promise. If the value is a promise, pass it through
* unaltered. If the value has a `then` method, it is presumed to be a promise
Expand All @@ -224,10 +213,7 @@ function Q(value) {
if (Q_isPromise(value)) {
return value;
} else if (isThenable(value)) {
if (!thenables.has(value)) {
thenables.set(value, new Promise(new Thenable(value)));
}
return thenables.get(value);
return new Promise(new Thenable(value));
} else {
return new Promise(new Fulfilled(value));
}
Expand Down Expand Up @@ -330,7 +316,7 @@ function Q_all(questions) {
} else {
++countDown;
promise = Q(promise);
promise.then(
promise.done(
function Q_all_eachFulfilled(value) {
answers[index] = value;
if (--countDown === 0) {
Expand Down Expand Up @@ -631,7 +617,7 @@ function Promise(handler) {
deferred.reject(error);
}
}
handlers.set(this, handler);
this._handler = handler;
}

/**
Expand Down Expand Up @@ -678,7 +664,7 @@ Promise.reject = Q_reject;
*/
Q.isPromise = Q_isPromise;
function Q_isPromise(object) {
return isObject(object) && !!handlers.get(object);
return isObject(object) && object instanceof Promise;
}

/**
Expand Down Expand Up @@ -1276,7 +1262,7 @@ Fulfilled.prototype.keys = function Fulfilled_keys() {
};

Fulfilled.prototype.iterate = function Fulfilled_iterate() {
return new Iterator(this.value);
return iterate(this.value);
};

Fulfilled.prototype.pull = function Fulfilled_pull() {
Expand Down Expand Up @@ -1359,7 +1345,7 @@ Pending.prototype.become = function Pending_become(promise) {
var handler = Q_getHandler(promise);
this.became = handler;

handlers.set(promise, handler);
promise._handler = handler;
this.promise = void 0;

this.messages.forEach(function Pending_become_eachMessage(message) {
Expand Down
4 changes: 2 additions & 2 deletions test/eta-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@ describe("estimate", function () {
// The composite ETA of thenPromise should be now + 100ms (this) +
// 200ms (then).
setTimeout(function () {
expect(thenPromise.getEstimate()).toBeNear(now + 300, 10);
expect(thenPromise.getEstimate()).toBeNear(now + 300, 20);
}, 0);

// But the actual time of completion will be now + 200ms (this
// actual) + 300ms (fulfilled actual)
setTimeout(function () {
expect(thenPromise.getEstimate()).toBeNear(now + 500, 10);
expect(thenPromise.getEstimate()).toBeNear(now + 500, 20);
done();
}, 600);
});
Expand Down

0 comments on commit 254347a

Please sign in to comment.