Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(734)

Unified Diff: src/promise.js

Issue 1098663002: Promise assimilation fix. Base URL: git://github.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/mjsunit/es6/promises.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/promise.js
diff --git a/src/promise.js b/src/promise.js
index 443a3b8c01a15d2d8cd4de98e4dfb10219fcb511..bae10fbc92bad2bcaec10fcccf4e9ca17d48b71a 100644
--- a/src/promise.js
+++ b/src/promise.js
@@ -100,16 +100,30 @@ var lastMicrotaskId = 0;
return x;
}
- function PromiseHandle(value, handler, deferred) {
+ function PromiseHandle(value, handler, deferred, thenable) {
try {
%DebugPushPromise(deferred.promise);
var result = handler(value);
- if (result === deferred.promise)
+ if (result === deferred.promise) {
throw MakeTypeError('promise_cyclic', [result]);
- else if (IsPromise(result))
+ } else if (IsPromise(result) && thenable) {
+ var then = result.then;
arv (Not doing code reviews) 2015/05/11 13:53:15 Isn't this extra Get observable?
yhirano 2015/05/12 06:09:19 In PromiseReactionJob[1], promiseCapability.[[Reso
+ if (IS_SPEC_FUNCTION(then)) {
+ %EnqueueMicrotask(function() {
+ try {
+ %_CallFunction(result, deferred.resolve, deferred.reject, then);
+ } catch(exception) {
+ try { deferred.reject(exception); } catch (e) { }
caitp (gmail) 2015/05/11 03:02:16 Is this not already handled by the enclosing try/c
caitp (gmail) 2015/05/11 03:06:05 wait, I get it --- I guess it's not
arv (Not doing code reviews) 2015/05/11 13:53:15 I think it is :-) Line 128
caitp (gmail) 2015/05/11 15:02:34 Yeah, but this one is in a closure passed to Enque
+ }
+ });
+ } else {
+ deferred.resolve(result);
caitp (gmail) 2015/05/11 03:02:16 This same branch is repeated a few times, maybe it
yhirano 2015/05/12 06:09:19 Hmm, I don't have a good idea to unify them (parti
+ }
+ } else if (IsPromise(result)) {
%_CallFunction(result, deferred.resolve, deferred.reject, PromiseChain);
- else
+ } else {
deferred.resolve(result);
+ }
} catch (exception) {
try { deferred.reject(exception); } catch (e) { }
} finally {
@@ -123,8 +137,8 @@ var lastMicrotaskId = 0;
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])
+ for (var i = 0; i < tasks.length; i += 3) {
caitp (gmail) 2015/05/11 03:02:16 This gets confusing, comments would be helpful
yhirano 2015/05/12 06:09:19 Done.
+ PromiseHandle(value, tasks[i], tasks[i + 1], tasks[i + 2])
}
if (instrumenting) {
%DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name });
@@ -137,6 +151,41 @@ var lastMicrotaskId = 0;
}
}
+ function PromiseChainInternal(onResolve, onReject, thenable) {
+ onResolve = IS_UNDEFINED(onResolve) ? PromiseIdResolveHandler : onResolve;
+ onReject = IS_UNDEFINED(onReject) ? PromiseIdRejectHandler : onReject;
+ var deferred = %_CallFunction(this.constructor, PromiseDeferred);
+ switch (GET_PRIVATE(this, promiseStatus)) {
+ case UNDEFINED:
+ throw MakeTypeError('not_a_promise', [this]);
+ case 0: // Pending
+ GET_PRIVATE(this, promiseOnResolve).push(onResolve, deferred, thenable);
+ GET_PRIVATE(this, promiseOnReject).push(onReject, deferred, thenable);
+ break;
+ case +1: // Resolved
+ PromiseEnqueue(GET_PRIVATE(this, promiseValue),
+ [onResolve, deferred, thenable],
+ +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, thenable],
+ -1);
+ break;
+ }
+ // Mark this promise as having handler.
+ SET_PRIVATE(this, promiseHasHandler, true);
+ if (DEBUG_IS_ACTIVE) {
+ %DebugPromiseEvent({ promise: deferred.promise, parentPromise: this });
+ }
+ return deferred.promise;
+ }
+
function PromiseIdResolveHandler(x) { return x }
function PromiseIdRejectHandler(r) { throw r }
@@ -219,38 +268,8 @@ var lastMicrotaskId = 0;
PromiseChain = function PromiseChain(onResolve, onReject) { // a.k.a.
// flatMap
- onResolve = IS_UNDEFINED(onResolve) ? PromiseIdResolveHandler : onResolve;
- onReject = IS_UNDEFINED(onReject) ? PromiseIdRejectHandler : onReject;
- var deferred = %_CallFunction(this.constructor, PromiseDeferred);
- switch (GET_PRIVATE(this, promiseStatus)) {
- case UNDEFINED:
- throw MakeTypeError('not_a_promise', [this]);
- case 0: // Pending
- GET_PRIVATE(this, promiseOnResolve).push(onResolve, deferred);
- GET_PRIVATE(this, promiseOnReject).push(onReject, deferred);
- break;
- case +1: // Resolved
- PromiseEnqueue(GET_PRIVATE(this, promiseValue),
- [onResolve, deferred],
- +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 });
- }
- return deferred.promise;
+ return %_CallFunction(this, onResolve, onReject, false,
+ PromiseChainInternal);
}
PromiseCatch = function PromiseCatch(onReject) {
@@ -271,10 +290,11 @@ var lastMicrotaskId = 0;
function(x) {
x = PromiseCoerce(constructor, x);
return x === that ? onReject(MakeTypeError('promise_cyclic', [x])) :
- IsPromise(x) ? x.then(onResolve, onReject) : onResolve(x);
+ IsPromise(x) ? x.then(onResolve, onReject) : onResolve(x);
},
onReject,
- PromiseChain
+ true,
+ PromiseChainInternal
);
}
@@ -343,7 +363,7 @@ var lastMicrotaskId = 0;
function PromiseHasUserDefinedRejectHandlerRecursive(promise) {
var queue = GET_PRIVATE(promise, promiseOnReject);
if (IS_UNDEFINED(queue)) return false;
- for (var i = 0; i < queue.length; i += 2) {
+ for (var i = 0; i < queue.length; i += 3) {
if (queue[i] != PromiseIdRejectHandler) return true;
if (PromiseHasUserDefinedRejectHandlerRecursive(queue[i + 1].promise)) {
return true;
« no previous file with comments | « no previous file | test/mjsunit/es6/promises.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698