Bug 1788969 - Reject async iterable result promises on error instead of throwing. r=edgar

Differential Revision: https://phabricator.services.mozilla.com/D156321
This commit is contained in:
Peter Van der Beken 2022-09-22 15:02:22 +00:00
parent 40e72fae73
commit 97b8e69531
6 changed files with 39 additions and 42 deletions

View File

@ -67,26 +67,28 @@ void KeyAndValueReturn(JSContext* aCx, JS::Handle<JS::Value> aKey,
aResult.set(&dictValue.toObject());
}
void ResolvePromiseForFinished(JSContext* aCx, Promise* aPromise,
ErrorResult& aRv) {
void ResolvePromiseForFinished(JSContext* aCx, Promise* aPromise) {
MOZ_ASSERT(aPromise);
ErrorResult error;
JS::Rooted<JSObject*> dict(aCx);
DictReturn(aCx, &dict, true, JS::UndefinedHandleValue, aRv);
if (aRv.Failed()) {
DictReturn(aCx, &dict, true, JS::UndefinedHandleValue, error);
if (error.Failed()) {
aPromise->MaybeReject(std::move(error));
return;
}
aPromise->MaybeResolve(dict);
}
void ResolvePromiseWithKeyOrValue(JSContext* aCx, Promise* aPromise,
JS::Handle<JS::Value> aKeyOrValue,
ErrorResult& aRv) {
JS::Handle<JS::Value> aKeyOrValue) {
MOZ_ASSERT(aPromise);
ErrorResult error;
JS::Rooted<JSObject*> dict(aCx);
DictReturn(aCx, &dict, false, aKeyOrValue, aRv);
if (aRv.Failed()) {
DictReturn(aCx, &dict, false, aKeyOrValue, error);
if (error.Failed()) {
aPromise->MaybeReject(std::move(error));
return;
}
aPromise->MaybeResolve(dict);
@ -94,13 +96,14 @@ void ResolvePromiseWithKeyOrValue(JSContext* aCx, Promise* aPromise,
void ResolvePromiseWithKeyAndValue(JSContext* aCx, Promise* aPromise,
JS::Handle<JS::Value> aKey,
JS::Handle<JS::Value> aValue,
ErrorResult& aRv) {
JS::Handle<JS::Value> aValue) {
MOZ_ASSERT(aPromise);
ErrorResult error;
JS::Rooted<JSObject*> dict(aCx);
KeyAndValueReturn(aCx, aKey, aValue, &dict, aRv);
if (aRv.Failed()) {
KeyAndValueReturn(aCx, aKey, aValue, &dict, error);
if (error.Failed()) {
aPromise->MaybeReject(std::move(error));
return;
}
aPromise->MaybeResolve(dict);

View File

@ -47,17 +47,14 @@ void KeyAndValueReturn(JSContext* aCx, JS::Handle<JS::Value> aKey,
JS::Handle<JS::Value> aValue,
JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv);
void ResolvePromiseForFinished(JSContext* aCx, Promise* aPromise,
ErrorResult& aRv);
void ResolvePromiseForFinished(JSContext* aCx, Promise* aPromise);
void ResolvePromiseWithKeyOrValue(JSContext* aCx, Promise* aPromise,
JS::Handle<JS::Value> aKeyOrValue,
ErrorResult& aRv);
JS::Handle<JS::Value> aKeyOrValue);
void ResolvePromiseWithKeyAndValue(JSContext* aCx, Promise* aPromise,
JS::Handle<JS::Value> aKey,
JS::Handle<JS::Value> aValue,
ErrorResult& aRv);
JS::Handle<JS::Value> aValue);
} // namespace iterator_utils
class IterableIteratorBase : public nsISupports {

View File

@ -90,34 +90,33 @@ void TestInterfaceAsyncIterableDouble::ResolvePromise(Iterator* aIterator) {
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(mParent))) {
data->mPromise->MaybeRejectWithInvalidStateError(
"Couldn't get the global.");
return;
}
JSContext* cx = jsapi.cx();
ErrorResult rv;
// Test data: ['a', 'b'], ['c', 'd'], ['e', 'f']
uint32_t idx = data->mIndex;
if (idx >= mValues.Length()) {
iterator_utils::ResolvePromiseForFinished(cx, data->mPromise, rv);
iterator_utils::ResolvePromiseForFinished(cx, data->mPromise);
} else {
JS::Rooted<JS::Value> key(cx);
JS::Rooted<JS::Value> value(cx);
switch (aIterator->GetIteratorType()) {
case IterableIteratorBase::IteratorType::Keys:
Unused << ToJSValue(cx, mValues[idx].first, &key);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, data->mPromise, key,
rv);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, data->mPromise, key);
break;
case IterableIteratorBase::IteratorType::Values:
Unused << ToJSValue(cx, mValues[idx].second, &value);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, data->mPromise, value,
rv);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, data->mPromise, value);
break;
case IterableIteratorBase::IteratorType::Entries:
Unused << ToJSValue(cx, mValues[idx].first, &key);
Unused << ToJSValue(cx, mValues[idx].second, &value);
iterator_utils::ResolvePromiseWithKeyAndValue(cx, data->mPromise, key,
value, rv);
value);
break;
}

View File

@ -97,35 +97,34 @@ void TestInterfaceAsyncIterableDoubleUnion::ResolvePromise(
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(mParent))) {
data->mPromise->MaybeRejectWithInvalidStateError(
"Couldn't get the global.");
return;
}
JSContext* cx = jsapi.cx();
ErrorResult rv;
// Test data:
// [long, 1], [string, "a"]
uint32_t idx = data->mIndex;
if (idx >= mValues.Length()) {
iterator_utils::ResolvePromiseForFinished(cx, data->mPromise, rv);
iterator_utils::ResolvePromiseForFinished(cx, data->mPromise);
} else {
JS::Rooted<JS::Value> key(cx);
JS::Rooted<JS::Value> value(cx);
switch (aIterator->GetIteratorType()) {
case IterableIteratorBase::IteratorType::Keys:
Unused << ToJSValue(cx, mValues[idx].first, &key);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, data->mPromise, key,
rv);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, data->mPromise, key);
break;
case IterableIteratorBase::IteratorType::Values:
Unused << ToJSValue(cx, mValues[idx].second, &value);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, data->mPromise, value,
rv);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, data->mPromise, value);
break;
case IterableIteratorBase::IteratorType::Entries:
Unused << ToJSValue(cx, mValues[idx].first, &key);
Unused << ToJSValue(cx, mValues[idx].second, &value);
iterator_utils::ResolvePromiseWithKeyAndValue(cx, data->mPromise, key,
value, rv);
value);
break;
}

View File

@ -98,18 +98,19 @@ void TestInterfaceAsyncIterableSingle::ResolvePromise(
IterableIteratorBase* aIterator, IteratorData* aData) {
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(mParent))) {
aData->mPromise->MaybeRejectWithInvalidStateError(
"Couldn't get the global.");
return;
}
JSContext* cx = jsapi.cx();
ErrorResult rv;
if (aData->mIndex >= 10) {
iterator_utils::ResolvePromiseForFinished(cx, aData->mPromise, rv);
iterator_utils::ResolvePromiseForFinished(cx, aData->mPromise);
} else {
JS::Rooted<JS::Value> value(cx);
Unused << ToJSValue(
cx, (int32_t)(aData->mIndex * 9 % 7 * aData->mMultiplier), &value);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, aData->mPromise, value,
rv);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, aData->mPromise, value);
aData->mIndex++;
}

View File

@ -50,8 +50,7 @@ struct ValueResolver<IterableIteratorBase::Keys> {
return NS_ERROR_INVALID_ARG;
}
iterator_utils::ResolvePromiseWithKeyOrValue(cx, aPromise.get(), key,
aError);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, aPromise.get(), key);
return NS_OK;
}
@ -81,8 +80,7 @@ struct ValueResolver<IterableIteratorBase::Values> {
return NS_ERROR_INVALID_ARG;
}
iterator_utils::ResolvePromiseWithKeyOrValue(cx, aPromise.get(), value,
aError);
iterator_utils::ResolvePromiseWithKeyOrValue(cx, aPromise.get(), value);
return NS_OK;
}
@ -118,7 +116,7 @@ struct ValueResolver<IterableIteratorBase::Entries> {
}
iterator_utils::ResolvePromiseWithKeyAndValue(cx, aPromise.get(), key,
value, aError);
value);
return NS_OK;
}
@ -159,7 +157,7 @@ class DoubleBufferQueueImpl
MOZ_ASSERT(aCx);
if (!aValue) {
iterator_utils::ResolvePromiseForFinished(aCx, aPromise.get(), aError);
iterator_utils::ResolvePromiseForFinished(aCx, aPromise.get());
return;
}