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

Unified Diff: src/promise.js

Issue 622783002: Make PromiseRejectCallback fire after end-of-turn. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 2 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 | « src/heap/heap.h ('k') | src/runtime/runtime.h » ('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 e402a18532647b96b6b07268858f95c4aa627064..350eef4eb8e6ca583f5a95ecd44a6e2c55a19f77 100644
--- a/src/promise.js
+++ b/src/promise.js
@@ -18,7 +18,9 @@ var PromiseReject;
var PromiseChain;
var PromiseCatch;
var PromiseThen;
-var PromiseHasRejectHandler;
+var PromiseScheduleUnhandledRejectMessage;
+var PromiseScheduleRevokeRejectMessage;
+var PromiseDispatchUnhandledRejectMessages;
var PromiseHasUserDefinedRejectHandler;
// mirror-debugger.js currently uses builtins.promiseStatus. It would be nice
@@ -31,8 +33,12 @@ 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 promiseHasHandler = %PromiseHasHandlerSymbol();
+var promiseHasHandler = GLOBAL_PRIVATE("Promise#hasHandler");
+// Enqueued promise message: true = revoke reject, false = unhandled reject
+var promiseMessage = GLOBAL_PRIVATE("Promise#message");
var lastMicrotaskId = 0;
+var promiseMicrotasksCount = 0;
+var enqueuedPromiseMessages;
(function() {
@@ -119,16 +125,18 @@ var lastMicrotaskId = 0;
function PromiseEnqueue(value, tasks, status) {
var id, name, instrumenting = DEBUG_IS_ACTIVE;
+ ++promiseMicrotasksCount;
%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])
+ PromiseHandle(value, tasks[i], tasks[i + 1]);
}
if (instrumenting) {
%DebugAsyncTaskEvent({ type: "didHandle", id: id, name: name });
}
+ --promiseMicrotasksCount;
});
if (instrumenting) {
id = ++lastMicrotaskId;
@@ -163,9 +171,11 @@ var lastMicrotaskId = 0;
// Check promise status to confirm that this reject has an effect.
// Call runtime for callbacks to the debugger or for unhandled reject.
if (GET_PRIVATE(promise, promiseStatus) == 0) {
- var debug_is_active = DEBUG_IS_ACTIVE;
- if (debug_is_active || !HAS_DEFINED_PRIVATE(promise, promiseHasHandler)) {
- %PromiseRejectEvent(promise, r, debug_is_active);
+ if (DEBUG_IS_ACTIVE) {
+ %DebugPromiseRejectEvent(promise, r);
+ }
+ if (!HAS_DEFINED_PRIVATE(promise, promiseHasHandler)) {
+ PromiseScheduleUnhandledRejectMessage(promise, r, false);
}
}
PromiseDone(promise, -1, r, promiseOnReject)
@@ -206,9 +216,7 @@ var lastMicrotaskId = 0;
if (this === $Promise) {
// Optimized case, avoid extra closure.
promise = PromiseSet(new $Promise(promiseRaw), -1, r);
- // The debug event for this would always be an uncaught promise reject,
- // which is usually simply noise. Do not trigger that debug event.
- %PromiseRejectEvent(promise, r, false);
+ PromiseScheduleUnhandledRejectMessage(promise, r, false);
} else {
promise = new this(function(resolve, reject) { reject(r) });
}
@@ -237,8 +245,8 @@ var lastMicrotaskId = 0;
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);
+ // Revoke previously triggered reject message.
+ PromiseScheduleRevokeRejectMessage(this);
}
PromiseEnqueue(GET_PRIVATE(this, promiseValue),
[onReject, deferred],
@@ -340,6 +348,41 @@ var lastMicrotaskId = 0;
// Utility for debugger
+ function PromiseScheduleUnhandledRejectMessage(promise, r, revoke) {
+ if (!enqueuedPromiseMessages) {
+ enqueuedPromiseMessages = new InternalArray;
+ %EnqueueMicrotask(PromiseDispatchUnhandledRejectMessages);
+ }
+ SET_PRIVATE(promise, promiseMessage, revoke);
+ enqueuedPromiseMessages.push(promise, r);
+ }
+
+ function PromiseScheduleRevokeRejectMessage(promise) {
+ if (HAS_DEFINED_PRIVATE(promise, promiseMessage)) {
+ DELETE_PRIVATE(promise, promiseMessage);
+ } else {
+ PromiseScheduleUnhandledRejectMessage(promise, UNDEFINED, true);
+ }
+ }
+
+ function PromiseDispatchUnhandledRejectMessages() {
+ if (promiseMicrotasksCount || %PendingMicrotaskCount()) {
+ %EnqueueMicrotask(PromiseDispatchUnhandledRejectMessages);
+ return;
+ }
+ var queue = enqueuedPromiseMessages;
+ enqueuedPromiseMessages = UNDEFINED;
+ for (var i = 0; i < queue.length; i += 2) {
+ var promise = queue[i];
+ if (HAS_DEFINED_PRIVATE(promise, promiseMessage)) {
+ var revoke = GET_PRIVATE(promise, promiseMessage);
+ DELETE_PRIVATE(promise, promiseMessage);
+ if (revoke) %PromiseRevokeRejectMessage(promise);
+ else %PromiseRejectMessage(promise, queue[i + 1]);
+ }
+ }
+ }
+
function PromiseHasUserDefinedRejectHandlerRecursive(promise) {
var queue = GET_PRIVATE(promise, promiseOnReject);
if (IS_UNDEFINED(queue)) return false;
« no previous file with comments | « src/heap/heap.h ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698