Bug 1734243 - Part 1: Add JS::SetAnyPromiseIsHandled r=arai

Differential Revision: https://phabricator.services.mozilla.com/D139505
This commit is contained in:
Kagami Sascha Rosylight 2022-02-25 02:32:04 +00:00
parent 263eb08d2e
commit 29d7c52a30
5 changed files with 62 additions and 15 deletions

View File

@ -858,12 +858,20 @@ Promise::PromiseState Promise::State() const {
return PromiseState::Pending;
}
void Promise::SetSettledPromiseIsHandled() {
bool Promise::SetSettledPromiseIsHandled() {
AutoAllowLegacyScriptExecution exemption;
AutoEntryScript aes(mGlobal, "Set settled promise handled");
JSContext* cx = aes.cx();
JS::RootedObject promiseObj(cx, mPromiseObj);
JS::SetSettledPromiseIsHandled(cx, promiseObj);
return JS::SetSettledPromiseIsHandled(cx, promiseObj);
}
bool Promise::SetAnyPromiseIsHandled() {
AutoAllowLegacyScriptExecution exemption;
AutoEntryScript aes(mGlobal, "Set any promise handled");
JSContext* cx = aes.cx();
JS::RootedObject promiseObj(cx, mPromiseObj);
return JS::SetAnyPromiseIsHandled(cx, promiseObj);
}
/* static */

View File

@ -182,7 +182,12 @@ class Promise : public SupportsWeakPtr {
// Mark a settled promise as already handled so that rejections will not
// be reported as unhandled.
void SetSettledPromiseIsHandled();
bool SetSettledPromiseIsHandled();
// Mark a promise as handled so that rejections will not be reported as
// unhandled. Consider using SetSettledPromiseIsHandled if this promise is
// expected to be settled.
[[nodiscard]] bool SetAnyPromiseIsHandled();
// WebIDL

View File

@ -362,9 +362,16 @@ extern JS_PUBLIC_API bool GetPromiseIsHandled(JS::HandleObject promise);
* |promise.[[PromiseIsHandled]]| to true and removes it from the list of
* unhandled rejected promises.
*/
extern JS_PUBLIC_API void SetSettledPromiseIsHandled(JSContext* cx,
extern JS_PUBLIC_API bool SetSettledPromiseIsHandled(JSContext* cx,
JS::HandleObject promise);
/*
* Given a promise (settled or not), sets |promise.[[PromiseIsHandled]]| to true
* and removes it from the list of unhandled rejected promises if it's settled.
*/
[[nodiscard]] extern JS_PUBLIC_API bool SetAnyPromiseIsHandled(
JSContext* cx, JS::HandleObject promise);
/**
* Returns a js::SavedFrame linked list of the stack that lead to the given
* Promise's allocation.

View File

@ -32,6 +32,14 @@ inline void SetSettledPromiseIsHandled(
cx->runtime()->removeUnhandledRejectedPromise(cx, unwrappedPromise);
}
inline void SetAnyPromiseIsHandled(
JSContext* cx, JS::Handle<PromiseObject*> unwrappedPromise) {
if (unwrappedPromise->state() != JS::PromiseState::Pending) {
cx->runtime()->removeUnhandledRejectedPromise(cx, unwrappedPromise);
}
unwrappedPromise->setHandled();
}
} // namespace js
#endif // builtin_Promise_inl_h

View File

@ -2606,9 +2606,8 @@ JS_PUBLIC_API JSObject* JS::GetPromisePrototype(JSContext* cx) {
return GlobalObject::getOrCreatePromisePrototype(cx, global);
}
JS_PUBLIC_API JS::PromiseState JS::GetPromiseState(
JS::HandleObject promiseObj_) {
PromiseObject* promiseObj = promiseObj_->maybeUnwrapIf<PromiseObject>();
JS_PUBLIC_API JS::PromiseState JS::GetPromiseState(JS::HandleObject promise) {
PromiseObject* promiseObj = promise->maybeUnwrapIf<PromiseObject>();
if (!promiseObj) {
return JS::PromiseState::Pending;
}
@ -2627,31 +2626,51 @@ JS_PUBLIC_API JS::Value JS::GetPromiseResult(JS::HandleObject promiseObj) {
: promise->reason();
}
JS_PUBLIC_API bool JS::GetPromiseIsHandled(JS::HandleObject promiseObj) {
PromiseObject* promise = &promiseObj->as<PromiseObject>();
return !promise->isUnhandled();
JS_PUBLIC_API bool JS::GetPromiseIsHandled(JS::HandleObject promise) {
PromiseObject* promiseObj = &promise->as<PromiseObject>();
return !promiseObj->isUnhandled();
}
JS_PUBLIC_API void JS::SetSettledPromiseIsHandled(JSContext* cx,
JS::HandleObject promise) {
static PromiseObject* UnwrapPromise(JSContext* cx, JS::HandleObject promise,
mozilla::Maybe<AutoRealm>& ar) {
AssertHeapIsIdle();
CHECK_THREAD(cx);
cx->check(promise);
mozilla::Maybe<AutoRealm> ar;
Rooted<PromiseObject*> promiseObj(cx);
PromiseObject* promiseObj;
if (IsWrapper(promise)) {
promiseObj = promise->maybeUnwrapAs<PromiseObject>();
if (!promiseObj) {
ReportAccessDenied(cx);
return;
return nullptr;
}
ar.emplace(cx, promiseObj);
} else {
promiseObj = promise.as<PromiseObject>();
}
return promiseObj;
}
JS_PUBLIC_API bool JS::SetSettledPromiseIsHandled(JSContext* cx,
JS::HandleObject promise) {
mozilla::Maybe<AutoRealm> ar;
Rooted<PromiseObject*> promiseObj(cx, UnwrapPromise(cx, promise, ar));
if (!promiseObj) {
return false;
}
js::SetSettledPromiseIsHandled(cx, promiseObj);
return true;
}
JS_PUBLIC_API bool JS::SetAnyPromiseIsHandled(JSContext* cx,
JS::HandleObject promise) {
mozilla::Maybe<AutoRealm> ar;
Rooted<PromiseObject*> promiseObj(cx, UnwrapPromise(cx, promise, ar));
if (!promiseObj) {
return false;
}
js::SetAnyPromiseIsHandled(cx, promiseObj);
return true;
}
JS_PUBLIC_API JSObject* JS::GetPromiseAllocationSite(JS::HandleObject promise) {