Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 254347a

Browse files
committed
Give up on weak maps
No more guarantees. Ten times faster.
1 parent a1293fa commit 254347a

File tree

3 files changed

+22
-36
lines changed

3 files changed

+22
-36
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
},
4141
"main": "q.js",
4242
"dependencies": {
43-
"asap": "^1.0.0",
44-
"collections": ">=2.0.1 <3.0.0"
43+
"asap": "^2.0.0",
44+
"weak-map": "^1.0.5"
4545
},
4646
"devDependencies": {
4747
"jshint": "^2.4.4",

q.js

Lines changed: 18 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ try {
4040
var qStartingLine = captureLine();
4141
var qFileName;
4242

43-
require("collections/shim");
44-
var WeakMap = require("collections/weak-map");
45-
var Iterator = require("collections/iterator");
43+
var WeakMap = require("weak-map");
4644
var asap = require("asap");
45+
var iterate = require("./iterate");
4746

47+
var typeOfObject = "object";
4848
function isObject(value) {
49-
return value === Object(value);
49+
return value !== null && typeof value === typeOfObject;
5050
}
5151

5252
// long stack traces
@@ -64,7 +64,7 @@ function makeStackTraceLong(error, promise) {
6464
error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1
6565
) {
6666
var stacks = [];
67-
for (var p = promise; !!p && handlers.get(p); p = handlers.get(p).became) {
67+
for (var p = promise; p instanceof Promise && p._handler; p = p._handler.became) {
6868
if (p.stack) {
6969
stacks.unshift(p.stack);
7070
}
@@ -179,33 +179,22 @@ function deprecate(callback, name, alternative) {
179179

180180
// end of long stack traces
181181

182-
var handlers = new WeakMap();
183-
182+
// When a deferred promise is forwarded to another promise, the old handler
183+
// becomes the new handler and all messages past and present flow to the next
184+
// handler.
184185
function Q_getHandler(promise) {
185-
var handler = handlers.get(promise);
186-
if (!handler || !handler.became) {
187-
return handler;
186+
var handler = promise._handler;
187+
while (handler && handler.became) {
188+
handler = handler.became;
188189
}
189-
handler = follow(handler);
190-
handlers.set(promise, handler);
190+
promise._handler = handler;
191191
return handler;
192192
}
193193

194-
function follow(handler) {
195-
if (!handler.became) {
196-
return handler;
197-
} else {
198-
handler.became = follow(handler.became);
199-
return handler.became;
200-
}
201-
}
202-
203194
var theViciousCycleError = new Error("Can't resolve a promise with itself");
204195
var theViciousCycleRejection = Q_reject(theViciousCycleError);
205196
var theViciousCycle = Q_getHandler(theViciousCycleRejection);
206197

207-
var thenables = new WeakMap();
208-
209198
/**
210199
* Coerces a value to a promise. If the value is a promise, pass it through
211200
* unaltered. If the value has a `then` method, it is presumed to be a promise
@@ -224,10 +213,7 @@ function Q(value) {
224213
if (Q_isPromise(value)) {
225214
return value;
226215
} else if (isThenable(value)) {
227-
if (!thenables.has(value)) {
228-
thenables.set(value, new Promise(new Thenable(value)));
229-
}
230-
return thenables.get(value);
216+
return new Promise(new Thenable(value));
231217
} else {
232218
return new Promise(new Fulfilled(value));
233219
}
@@ -330,7 +316,7 @@ function Q_all(questions) {
330316
} else {
331317
++countDown;
332318
promise = Q(promise);
333-
promise.then(
319+
promise.done(
334320
function Q_all_eachFulfilled(value) {
335321
answers[index] = value;
336322
if (--countDown === 0) {
@@ -631,7 +617,7 @@ function Promise(handler) {
631617
deferred.reject(error);
632618
}
633619
}
634-
handlers.set(this, handler);
620+
this._handler = handler;
635621
}
636622

637623
/**
@@ -678,7 +664,7 @@ Promise.reject = Q_reject;
678664
*/
679665
Q.isPromise = Q_isPromise;
680666
function Q_isPromise(object) {
681-
return isObject(object) && !!handlers.get(object);
667+
return isObject(object) && object instanceof Promise;
682668
}
683669

684670
/**
@@ -1276,7 +1262,7 @@ Fulfilled.prototype.keys = function Fulfilled_keys() {
12761262
};
12771263

12781264
Fulfilled.prototype.iterate = function Fulfilled_iterate() {
1279-
return new Iterator(this.value);
1265+
return iterate(this.value);
12801266
};
12811267

12821268
Fulfilled.prototype.pull = function Fulfilled_pull() {
@@ -1359,7 +1345,7 @@ Pending.prototype.become = function Pending_become(promise) {
13591345
var handler = Q_getHandler(promise);
13601346
this.became = handler;
13611347

1362-
handlers.set(promise, handler);
1348+
promise._handler = handler;
13631349
this.promise = void 0;
13641350

13651351
this.messages.forEach(function Pending_become_eachMessage(message) {

test/eta-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,13 @@ describe("estimate", function () {
107107
// The composite ETA of thenPromise should be now + 100ms (this) +
108108
// 200ms (then).
109109
setTimeout(function () {
110-
expect(thenPromise.getEstimate()).toBeNear(now + 300, 10);
110+
expect(thenPromise.getEstimate()).toBeNear(now + 300, 20);
111111
}, 0);
112112

113113
// But the actual time of completion will be now + 200ms (this
114114
// actual) + 300ms (fulfilled actual)
115115
setTimeout(function () {
116-
expect(thenPromise.getEstimate()).toBeNear(now + 500, 10);
116+
expect(thenPromise.getEstimate()).toBeNear(now + 500, 20);
117117
done();
118118
}, 600);
119119
});

0 commit comments

Comments
 (0)