Index: src/js/promise.js |
diff --git a/src/js/promise.js b/src/js/promise.js |
index f2fcc477996afc47d1954b71504ecd7b48f73943..8997c93e0e66fa3d17ad0a804ee8075a25d538d5 100644 |
--- a/src/js/promise.js |
+++ b/src/js/promise.js |
@@ -21,6 +21,8 @@ var promiseRejectReactionsSymbol = |
utils.ImportNow("promise_reject_reactions_symbol"); |
var promiseFulfillReactionsSymbol = |
utils.ImportNow("promise_fulfill_reactions_symbol"); |
+var promiseDeferredReactionsSymbol = |
+ utils.ImportNow("promise_deferred_reactions_symbol"); |
var promiseRawSymbol = utils.ImportNow("promise_raw_symbol"); |
var promiseStateSymbol = utils.ImportNow("promise_state_symbol"); |
var promiseResultSymbol = utils.ImportNow("promise_result_symbol"); |
@@ -98,11 +100,13 @@ var GlobalPromise = function Promise(resolver) { |
// Core functionality. |
-function PromiseSet(promise, status, value, onResolve, onReject) { |
+function PromiseSet( |
+ promise, status, value, onResolve, onReject, deferred) { |
adamk
2016/05/25 19:18:57
None of the callers pass more than 3 arguments any
gsathya
2016/05/25 21:46:35
Done.
|
SET_PRIVATE(promise, promiseStateSymbol, status); |
SET_PRIVATE(promise, promiseResultSymbol, value); |
SET_PRIVATE(promise, promiseFulfillReactionsSymbol, onResolve); |
adamk
2016/05/25 19:18:57
Maybe add a comment here with a version of the thi
gsathya
2016/05/25 21:46:35
Done. Let me know if you can think of a more cohes
|
SET_PRIVATE(promise, promiseRejectReactionsSymbol, onReject); |
+ SET_PRIVATE(promise, promiseDeferredReactionsSymbol, deferred); |
return promise; |
} |
@@ -115,13 +119,17 @@ function PromiseCreateAndSet(status, value) { |
function PromiseInit(promise) { |
return PromiseSet( |
- promise, kPending, UNDEFINED, new InternalArray, new InternalArray) |
+ promise, kPending, UNDEFINED, UNDEFINED, UNDEFINED, UNDEFINED); |
} |
function PromiseDone(promise, status, value, promiseQueue) { |
if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) { |
var tasks = GET_PRIVATE(promise, promiseQueue); |
- if (tasks.length) PromiseEnqueue(value, tasks, status); |
+ if (!IS_NULL_OR_UNDEFINED(tasks)) { |
adamk
2016/05/25 19:18:57
It should never be null, right? Can this just be I
gsathya
2016/05/25 21:46:35
Done.
|
+ var tasks = GET_PRIVATE(promise, promiseQueue); |
+ var deferreds = GET_PRIVATE(promise, promiseDeferredReactionsSymbol); |
+ PromiseEnqueue(value, tasks, deferreds, status); |
+ } |
PromiseSet(promise, status, value); |
} |
} |
@@ -139,14 +147,18 @@ function PromiseHandle(value, handler, deferred) { |
} |
} |
-function PromiseEnqueue(value, tasks, status) { |
+function PromiseEnqueue(value, tasks, deferreds, status) { |
var id, name, instrumenting = DEBUG_IS_ACTIVE; |
%EnqueueMicrotask(function() { |
if (instrumenting) { |
%DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name }); |
} |
- for (var i = 0; i < tasks.length; i += 2) { |
- PromiseHandle(value, tasks[i], tasks[i + 1]) |
+ if (IS_ARRAY(tasks)) { |
+ for (var i = 0; i < tasks.length; i += 1) { |
+ PromiseHandle(value, tasks[i], deferreds[i]); |
+ } |
+ } else { |
+ PromiseHandle(value, tasks, deferreds); |
} |
if (instrumenting) { |
%DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name }); |
@@ -319,14 +331,37 @@ function PromiseThen(onResolve, onReject) { |
var deferred = NewPromiseCapability(constructor); |
switch (status) { |
case kPending: |
adamk
2016/05/25 19:18:57
This whole block seems like it should be encapsula
gsathya
2016/05/25 21:46:34
Done.
|
- GET_PRIVATE(this, promiseFulfillReactionsSymbol).push(onResolve, |
- deferred); |
- GET_PRIVATE(this, promiseRejectReactionsSymbol).push(onReject, deferred); |
+ var resolveCallbacks = GET_PRIVATE(this, promiseFulfillReactionsSymbol); |
+ if (IS_NULL_OR_UNDEFINED(resolveCallbacks)) { |
+ SET_PRIVATE(this, promiseDeferredReactionsSymbol, deferred); |
+ SET_PRIVATE(this, promiseFulfillReactionsSymbol, onResolve); |
+ SET_PRIVATE(this, promiseRejectReactionsSymbol, onReject); |
+ } else if (!IS_ARRAY(resolveCallbacks)) { |
adamk
2016/05/25 19:18:57
Did you figure out if Bluebird goes down this path
gsathya
2016/05/25 21:46:35
Bluebird doesn't create arrays at all, they just s
adamk
2016/05/25 21:57:43
Sorry, when I say "Bluebird" I meant the benchmark
adamk
2016/05/25 23:41:35
As discussed offline, though this path isn't cover
|
+ var deferreds = new InternalArray(); |
+ var resolveCallbacks = new InternalArray(); |
+ var rejectCallbacks = new InternalArray(); |
+ |
+ deferreds.push(GET_PRIVATE(this, promiseDeferredReactionsSymbol)); |
+ resolveCallbacks.push(GET_PRIVATE(this, promiseFulfillReactionsSymbol)); |
adamk
2016/05/25 19:18:57
This extra GET isn't needed, you already had an ar
gsathya
2016/05/25 21:46:35
Done. Let me know if you have a better name for th
|
+ rejectCallbacks.push(GET_PRIVATE(this, promiseRejectReactionsSymbol)); |
+ |
+ deferreds.push(deferred); |
+ resolveCallbacks.push(onResolve); |
+ rejectCallbacks.push(onReject); |
+ |
+ SET_PRIVATE(this, promiseDeferredReactionsSymbol, deferreds); |
+ SET_PRIVATE(this, promiseFulfillReactionsSymbol, resolveCallbacks); |
+ SET_PRIVATE(this, promiseRejectReactionsSymbol, rejectCallbacks); |
+ } else { |
+ GET_PRIVATE(this, promiseDeferredReactionsSymbol).push(deferred); |
+ GET_PRIVATE(this, promiseFulfillReactionsSymbol).push(onResolve); |
adamk
2016/05/25 19:18:57
This extra GET isn't needed, you already have an a
gsathya
2016/05/25 21:46:35
Done.
|
+ GET_PRIVATE(this, promiseRejectReactionsSymbol).push(onReject); |
+ } |
break; |
case kFulfilled: |
PromiseEnqueue(GET_PRIVATE(this, promiseResultSymbol), |
- [onResolve, deferred], |
- kFulfilled); |
+ onResolve, deferred, |
+ kFulfilled, 1); |
adamk
2016/05/25 19:18:57
Looks like a stray change from the previous approa
gsathya
2016/05/25 21:46:34
Done.
|
break; |
case kRejected: |
if (!HAS_DEFINED_PRIVATE(this, promiseHasHandlerSymbol)) { |
@@ -335,8 +370,8 @@ function PromiseThen(onResolve, onReject) { |
%PromiseRevokeReject(this); |
} |
PromiseEnqueue(GET_PRIVATE(this, promiseResultSymbol), |
- [onReject, deferred], |
- kRejected); |
+ onReject, deferred, |
+ kRejected, 1); |
adamk
2016/05/25 19:18:57
Same here.
gsathya
2016/05/25 21:46:35
Done.
|
break; |
} |
// Mark this promise as having handler. |
@@ -447,17 +482,24 @@ function PromiseRace(iterable) { |
function PromiseHasUserDefinedRejectHandlerRecursive(promise) { |
var queue = GET_PRIVATE(promise, promiseRejectReactionsSymbol); |
+ var deferreds = GET_PRIVATE(promise, promiseDeferredReactionsSymbol); |
if (IS_UNDEFINED(queue)) return false; |
- for (var i = 0; i < queue.length; i += 2) { |
+ if (!IS_ARRAY(queue)) { |
+ queue = [queue]; |
adamk
2016/05/25 19:18:57
This is a neat trick, I'll have to think about whe
gsathya
2016/05/25 21:46:35
:P Happy to change it, let me know
adamk
2016/05/25 23:41:35
Please do change it to a factored-out function and
gsathya
2016/05/26 22:18:47
Done.
|
+ deferreds = [deferreds]; |
+ } |
+ for (var i = 0; i < queue.length; i += 1) { |
var handler = queue[i]; |
if (handler !== PromiseIdRejectHandler) { |
- var deferred = GET_PRIVATE(handler, promiseCombinedDeferredSymbol); |
- if (IS_UNDEFINED(deferred)) return true; |
- if (PromiseHasUserDefinedRejectHandlerRecursive(deferred.promise)) { |
+ var combinedDeferred = |
+ GET_PRIVATE(handler, promiseCombinedDeferredSymbol); |
+ if (IS_UNDEFINED(combinedDeferred)) return true; |
+ if (PromiseHasUserDefinedRejectHandlerRecursive( |
+ combinedDeferred.promise)) { |
return true; |
} |
} else if (PromiseHasUserDefinedRejectHandlerRecursive( |
- queue[i + 1].promise)) { |
+ deferreds[i].promise)) { |
return true; |
} |
} |