Promises: Add is_silent flag and ignore rejects when it is set

This allows for marking promises as silent. Setting this flag prevents
the debugger from pausing when the promise rejects.

Bug: chromium:1132506
Change-Id: I260e52faa45ebedd9e8d84e092bd0260e828a902
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3001354
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75595}
This commit is contained in:
Jesper van den Ende 2021-07-06 23:26:10 +02:00 committed by V8 LUCI CQ
parent 2acaa66ffa
commit f5fa069468
9 changed files with 30 additions and 5 deletions

View File

@ -126,6 +126,7 @@ Jay Freeman <saurik@saurik.com>
James Pike <g00gle@chilon.net>
James M Snell <jasnell@gmail.com>
Javad Amiri <javad.amiri@anu.edu.au>
Jesper van den Ende <jespertheend@gmail.com>
Ji Qiu <qiuji@iscas.ac.cn>
Jianghua Yang <jianghua.yjh@alibaba-inc.com>
Jiawen Geng <technicalcute@gmail.com>

View File

@ -4908,6 +4908,12 @@ class V8_EXPORT Promise : public Object {
*/
void MarkAsHandled();
/**
* Marks this promise as silent to prevent pausing the debugger when the
* promise is rejected.
*/
void MarkAsSilent();
V8_INLINE static Promise* Cast(Value* obj);
static const int kEmbedderFieldCount = V8_PROMISE_INTERNAL_FIELD_COUNT;

View File

@ -7482,6 +7482,11 @@ void Promise::MarkAsHandled() {
js_promise->set_has_handler(true);
}
void Promise::MarkAsSilent() {
i::Handle<i::JSPromise> js_promise = Utils::OpenHandle(this);
js_promise->set_is_silent(true);
}
Local<Value> Proxy::GetTarget() {
i::Handle<i::JSProxy> self = Utils::OpenHandle(this);
i::Handle<i::Object> target(self->target(), self->GetIsolate());

View File

@ -41,6 +41,7 @@ macro PromiseInit(promise: JSPromise): void {
status: PromiseState::kPending,
has_handler: false,
handled_hint: false,
is_silent: false,
async_task_id: 0
});
promise_internal::ZeroOutEmbedderOffsets(promise);
@ -60,6 +61,7 @@ macro InnerNewJSPromise(implicit context: Context)(): JSPromise {
status: PromiseState::kPending,
has_handler: false,
handled_hint: false,
is_silent: false,
async_task_id: 0
});
return promise;

View File

@ -2032,16 +2032,20 @@ void Debug::OnException(Handle<Object> exception, Handle<Object> promise,
bool uncaught = catch_type == Isolate::NOT_CAUGHT;
if (promise->IsJSObject()) {
Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
Handle<JSObject> jsobject = Handle<JSObject>::cast(promise);
// Mark the promise as already having triggered a message.
Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
Object::SetProperty(isolate_, jspromise, key, key, StoreOrigin::kMaybeKeyed,
Object::SetProperty(isolate_, jsobject, key, key, StoreOrigin::kMaybeKeyed,
Just(ShouldThrow::kThrowOnError))
.Assert();
// Check whether the promise reject is considered an uncaught exception.
if (jspromise->IsJSPromise()) {
uncaught = !isolate_->PromiseHasUserDefinedRejectHandler(
Handle<JSPromise>::cast(jspromise));
if (jsobject->IsJSPromise()) {
Handle<JSPromise> jspromise = Handle<JSPromise>::cast(jsobject);
// Ignore the exception if the promise was marked as silent
if (jspromise->is_silent()) return;
uncaught = !isolate_->PromiseHasUserDefinedRejectHandler(jspromise);
} else {
uncaught = true;
}

View File

@ -676,6 +676,7 @@ void JSPromise::JSPromisePrint(std::ostream& os) {
}
os << "\n - has_handler: " << has_handler();
os << "\n - handled_hint: " << handled_hint();
os << "\n - is_silent: " << is_silent();
JSObjectPrintBody(os, *this);
}

View File

@ -22,6 +22,7 @@ TQ_OBJECT_CONSTRUCTORS_IMPL(JSPromise)
BOOL_ACCESSORS(JSPromise, flags, has_handler, HasHandlerBit::kShift)
BOOL_ACCESSORS(JSPromise, flags, handled_hint, HandledHintBit::kShift)
BOOL_ACCESSORS(JSPromise, flags, is_silent, IsSilentBit::kShift)
Object JSPromise::result() const {
DCHECK_NE(Promise::kPending, status());

View File

@ -42,6 +42,10 @@ class JSPromise : public TorqueGeneratedJSPromise<JSPromise, JSObject> {
// block in an async function.
DECL_BOOLEAN_ACCESSORS(handled_hint)
// [is_silent]: Whether this promise should cause the debugger to pause when
// rejected.
DECL_BOOLEAN_ACCESSORS(is_silent)
int async_task_id() const;
void set_async_task_id(int id);

View File

@ -6,6 +6,7 @@ bitfield struct JSPromiseFlags extends uint31 {
status: PromiseState: 2 bit;
has_handler: bool: 1 bit;
handled_hint: bool: 1 bit;
is_silent: bool: 1 bit;
async_task_id: int32: 22 bit;
}