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

Unified Diff: src/js/promise.js

Issue 2244003003: Change which ExceptionEvents are triggered by Promises (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fixed typos Created 4 years, 4 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/js/harmony-async-await.js ('k') | src/runtime/runtime.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/js/promise.js
diff --git a/src/js/promise.js b/src/js/promise.js
index b50fc80b305bdcfd509e479cfb703171b85eac9b..9e4179ae30d7013bbbc16a58cca7acb2dc0c2584 100644
--- a/src/js/promise.js
+++ b/src/js/promise.js
@@ -44,7 +44,7 @@ var lastMicrotaskId = 0;
// ES#sec-createresolvingfunctions
// CreateResolvingFunctions ( promise )
-function CreateResolvingFunctions(promise) {
+function CreateResolvingFunctions(promise, debugEvent) {
var alreadyResolved = false;
// ES#sec-promise-resolve-functions
@@ -60,7 +60,7 @@ function CreateResolvingFunctions(promise) {
var reject = reason => {
if (alreadyResolved === true) return;
alreadyResolved = true;
- RejectPromise(promise, reason);
+ RejectPromise(promise, reason, debugEvent);
};
return {
@@ -83,7 +83,8 @@ var GlobalPromise = function Promise(executor) {
}
var promise = PromiseInit(%_NewObject(GlobalPromise, new.target));
- var callbacks = CreateResolvingFunctions(promise);
+ // Calling the reject function would be a new exception, so debugEvent = true
+ var callbacks = CreateResolvingFunctions(promise, true);
var debug_is_active = DEBUG_IS_ACTIVE;
try {
if (debug_is_active) %DebugPushPromise(promise);
@@ -238,14 +239,16 @@ function PromiseCreate() {
// Promise Resolve Functions, steps 6-13
function ResolvePromise(promise, resolution) {
if (resolution === promise) {
- return RejectPromise(promise, %make_type_error(kPromiseCyclic, resolution));
+ return RejectPromise(promise,
+ %make_type_error(kPromiseCyclic, resolution),
+ true);
}
if (IS_RECEIVER(resolution)) {
// 25.4.1.3.2 steps 8-12
try {
var then = resolution.then;
} catch (e) {
- return RejectPromise(promise, e);
+ return RejectPromise(promise, e, true);
}
// Resolution is a native promise and if it's already resolved or
@@ -268,7 +271,8 @@ function ResolvePromise(promise, resolution) {
// Revoke previously triggered reject event.
%PromiseRevokeReject(resolution);
}
- RejectPromise(promise, thenableValue);
+ // Don't cause a debug event as this case is forwarding a rejection
+ RejectPromise(promise, thenableValue, false);
SET_PRIVATE(resolution, promiseHasHandlerSymbol, true);
return;
}
@@ -283,7 +287,9 @@ function ResolvePromise(promise, resolution) {
if (instrumenting) {
%DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name });
}
- var callbacks = CreateResolvingFunctions(promise);
+ // These resolving functions simply forward the exception, so
+ // don't create a new debugEvent.
+ var callbacks = CreateResolvingFunctions(promise, false);
try {
%_Call(then, resolution, callbacks.resolve, callbacks.reject);
} catch (e) {
@@ -305,26 +311,35 @@ function ResolvePromise(promise, resolution) {
// ES#sec-rejectpromise
// RejectPromise ( promise, reason )
-function RejectPromise(promise, reason) {
+function RejectPromise(promise, reason, debugEvent) {
// Check promise status to confirm that this reject has an effect.
// Call runtime for callbacks to the debugger or for unhandled reject.
+ // The debugEvent parameter sets whether a debug ExceptionEvent should
+ // be triggered. It should be set to false when forwarding a rejection
+ // rather than creating a new one.
if (GET_PRIVATE(promise, promiseStateSymbol) === kPending) {
- var debug_is_active = DEBUG_IS_ACTIVE;
- if (debug_is_active ||
+ // This check is redundant with checks in the runtime, but it may help
+ // avoid unnecessary runtime calls.
+ if ((debugEvent && DEBUG_IS_ACTIVE) ||
!HAS_DEFINED_PRIVATE(promise, promiseHasHandlerSymbol)) {
- %PromiseRejectEvent(promise, reason, debug_is_active);
+ %PromiseRejectEvent(promise, reason, debugEvent);
}
}
FulfillPromise(promise, kRejected, reason, promiseRejectReactionsSymbol)
}
+// Export to bindings
+function DoRejectPromise(promise, reason) {
+ return RejectPromise(promise, reason, true);
+}
+
// ES#sec-newpromisecapability
// NewPromiseCapability ( C )
-function NewPromiseCapability(C) {
+function NewPromiseCapability(C, debugEvent) {
if (C === GlobalPromise) {
// Optimized case, avoid extra closure.
var promise = PromiseInit(new GlobalPromise(promiseRawSymbol));
- var callbacks = CreateResolvingFunctions(promise);
+ var callbacks = CreateResolvingFunctions(promise, debugEvent);
return {
promise: promise,
resolve: callbacks.resolve,
@@ -355,12 +370,12 @@ function PromiseReject(r) {
if (this === GlobalPromise) {
// Optimized case, avoid extra closure.
var promise = PromiseCreateAndSet(kRejected, 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);
+ // Trigger debug events if the debugger is on, as Promise.reject is
+ // equivalent to throwing an exception directly.
+ %PromiseRejectEventFromStack(promise, r);
return promise;
} else {
- var promiseCapability = NewPromiseCapability(this);
+ var promiseCapability = NewPromiseCapability(this, true);
%_Call(promiseCapability.reject, UNDEFINED, r);
return promiseCapability.promise;
}
@@ -369,7 +384,11 @@ function PromiseReject(r) {
// Shortcut Promise.reject and Promise.resolve() implementations, used by
// Async Functions implementation.
function PromiseCreateRejected(r) {
- return %_Call(PromiseReject, GlobalPromise, r);
+ var promise = PromiseCreateAndSet(kRejected, r);
+ // This is called from the desugaring of async/await; no reason to
+ // create a redundant reject event.
+ %PromiseRejectEvent(promise, r, false);
+ return promise;
}
function PromiseCreateResolved(value) {
@@ -427,7 +446,9 @@ function PromiseThen(onResolve, onReject) {
}
var constructor = SpeciesConstructor(this, GlobalPromise);
- var resultCapability = NewPromiseCapability(constructor);
+ // Pass false for debugEvent so .then chaining does not trigger
+ // redundant ExceptionEvents.
+ var resultCapability = NewPromiseCapability(constructor, false);
return PerformPromiseThen(this, onResolve, onReject, resultCapability);
}
@@ -454,7 +475,8 @@ function PromiseResolve(x) {
return promise;
}
- var promiseCapability = NewPromiseCapability(this);
+ // debugEvent is not so meaningful here as it will be resolved
+ var promiseCapability = NewPromiseCapability(this, true);
var resolveResult = %_Call(promiseCapability.resolve, UNDEFINED, x);
return promiseCapability.promise;
}
@@ -466,7 +488,9 @@ function PromiseAll(iterable) {
throw %make_type_error(kCalledOnNonObject, "Promise.all");
}
- var deferred = NewPromiseCapability(this);
+ // false debugEvent so that forwarding the rejection through all does not
+ // trigger redundant ExceptionEvents
+ var deferred = NewPromiseCapability(this, false);
var resolutions = new InternalArray();
var count;
@@ -517,7 +541,9 @@ function PromiseRace(iterable) {
throw %make_type_error(kCalledOnNonObject, PromiseRace);
}
- var deferred = NewPromiseCapability(this);
+ // false debugEvent so that forwarding the rejection through race does not
+ // trigger redundant ExceptionEvents
+ var deferred = NewPromiseCapability(this, false);
try {
for (var value of iterable) {
this.resolve(value).then(deferred.resolve, deferred.reject);
@@ -598,7 +624,7 @@ utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [
"promise_catch", PromiseCatch,
"promise_create", PromiseCreate,
"promise_has_user_defined_reject_handler", PromiseHasUserDefinedRejectHandler,
- "promise_reject", RejectPromise,
+ "promise_reject", DoRejectPromise,
"promise_resolve", ResolvePromise,
"promise_then", PromiseThen,
"promise_create_rejected", PromiseCreateRejected,
@@ -611,7 +637,7 @@ utils.InstallFunctions(GlobalPromise.prototype, DONT_ENUM, [
utils.InstallFunctions(extrasUtils, 0, [
"createPromise", PromiseCreate,
"resolvePromise", ResolvePromise,
- "rejectPromise", RejectPromise
+ "rejectPromise", DoRejectPromise
]);
utils.Export(function(to) {
« no previous file with comments | « src/js/harmony-async-await.js ('k') | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698