Chromium Code Reviews| 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; |
| } |
| } |