Chromium Code Reviews| Index: src/promise.js |
| diff --git a/src/promise.js b/src/promise.js |
| index 37c10ec08eb298d5543738531168fe0315ca7854..1eadea2252363d43a8f4bfbadcac6b72eac3e191 100644 |
| --- a/src/promise.js |
| +++ b/src/promise.js |
| @@ -19,6 +19,7 @@ var PromiseChain; |
| var PromiseCatch; |
| var PromiseThen; |
| var PromiseHasRejectHandler; |
| +var PromiseHasUserDefinedRejectHandler; |
| // mirror-debugger.js currently uses builtins.promiseStatus. It would be nice |
| // if we could move these property names into the closure below. |
| @@ -30,9 +31,10 @@ var promiseValue = GLOBAL_PRIVATE("Promise#value"); |
| var promiseOnResolve = GLOBAL_PRIVATE("Promise#onResolve"); |
| var promiseOnReject = GLOBAL_PRIVATE("Promise#onReject"); |
| var promiseRaw = GLOBAL_PRIVATE("Promise#raw"); |
| -var promiseDebug = GLOBAL_PRIVATE("Promise#debug"); |
| +var promiseHasHandler = %PromiseHasHandlerSymbol(); |
| var lastMicrotaskId = 0; |
| + |
| (function() { |
| var $Promise = function Promise(resolver) { |
| @@ -159,11 +161,10 @@ var lastMicrotaskId = 0; |
| PromiseReject = function PromiseReject(promise, r) { |
| // Check promise status to confirm that this reject has an effect. |
| - // Check promiseDebug property to avoid duplicate event. |
| - if (DEBUG_IS_ACTIVE && |
| - GET_PRIVATE(promise, promiseStatus) == 0 && |
| - !HAS_DEFINED_PRIVATE(promise, promiseDebug)) { |
| - %DebugPromiseRejectEvent(promise, r); |
| + // Call runtime for callbacks to the debugger or for unhandled reject. |
| + if (GET_PRIVATE(promise, promiseStatus) == 0 && |
| + (DEBUG_IS_ACTIVE || !HAS_DEFINED_PRIVATE(promise, promiseHasHandler))) { |
| + %PromiseRejectEvent(promise, r); |
| } |
| PromiseDone(promise, -1, r, promiseOnReject) |
| } |
| @@ -199,12 +200,17 @@ var lastMicrotaskId = 0; |
| } |
| function PromiseRejected(r) { |
| + var promise; |
| if (this === $Promise) { |
| // Optimized case, avoid extra closure. |
| - return PromiseSet(new $Promise(promiseRaw), -1, r); |
| + promise = PromiseSet(new $Promise(promiseRaw), -1, r); |
| } else { |
| - return new this(function(resolve, reject) { reject(r) }); |
| + promise = new this(function(resolve, reject) { reject(r) }); |
| } |
| + // This promise is expected to have the reject state. Mark it to avoid |
| + // triggering an unnecessary callback. |
| + SET_PRIVATE(promise, promiseHasHandler, true); |
|
domenic_domenicdenicola.com
2014/09/30 10:30:42
This doesn't seem correct. The promise doesn't hav
Yang
2014/09/30 10:38:50
If I reject a promise by returning a rejected prom
|
| + return promise; |
| } |
| // Simple chaining. |
| @@ -227,11 +233,18 @@ var lastMicrotaskId = 0; |
| +1); |
| break; |
| case -1: // Rejected |
| + if (!HAS_DEFINED_PRIVATE(this, promiseHasHandler)) { |
| + // Promise has already been rejected, but had no handler. |
| + // Revoke previously triggered reject event. |
| + %PromiseRevokeReject(this); |
| + } |
| PromiseEnqueue(GET_PRIVATE(this, promiseValue), |
| [onReject, deferred], |
| -1); |
| break; |
| } |
| + // Mark this promise as having handler. |
| + SET_PRIVATE(this, promiseHasHandler, true); |
| if (DEBUG_IS_ACTIVE) { |
| %DebugPromiseEvent({ promise: deferred.promise, parentPromise: this }); |
| } |
| @@ -325,22 +338,24 @@ var lastMicrotaskId = 0; |
| // Utility for debugger |
| - function PromiseHasRejectHandlerRecursive(promise) { |
| + function PromiseHasUserDefinedRejectHandlerRecursive(promise) { |
| var queue = GET_PRIVATE(promise, promiseOnReject); |
| if (IS_UNDEFINED(queue)) return false; |
| - // Do a depth first search for a reject handler that's not |
| - // the default PromiseIdRejectHandler. |
| for (var i = 0; i < queue.length; i += 2) { |
| if (queue[i] != PromiseIdRejectHandler) return true; |
| - if (PromiseHasRejectHandlerRecursive(queue[i + 1].promise)) return true; |
| + if (PromiseHasUserDefinedRejectHandlerRecursive(queue[i + 1].promise)) { |
| + return true; |
| + } |
| } |
| return false; |
| } |
| - PromiseHasRejectHandler = function PromiseHasRejectHandler() { |
| - // Mark promise as already having triggered a reject event. |
| - SET_PRIVATE(this, promiseDebug, true); |
| - return PromiseHasRejectHandlerRecursive(this); |
| + // Return whether the promise will be handled by a user-defined reject |
| + // handler somewhere down the promise chain. For this, we do a depth-first |
| + // search for a reject handler that's not the default PromiseIdRejectHandler. |
| + PromiseHasUserDefinedRejectHandler = |
| + function PromiseHasUserDefinedRejectHandler() { |
| + return PromiseHasUserDefinedRejectHandlerRecursive(this); |
| }; |
| // ------------------------------------------------------------------- |