1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-09 09:34:57 +09:00

LibJS: Add a TRY_OR_CLOSE_ITERATOR macro for IfAbruptCloseIterator

Behaves just like TRY_OR_REJECT for promises.
This commit is contained in:
Timothy Flynn 2025-04-28 18:22:32 -04:00 committed by Tim Flynn
parent 568524f8ba
commit 908349f8fe
Notes: github-actions[bot] 2025-04-29 11:34:16 +00:00
3 changed files with 25 additions and 20 deletions

View file

@ -237,22 +237,16 @@ ThrowCompletionOr<GroupsType> group_by(VM& vm, Value items, Value callback_funct
auto value = next.release_value();
// e. Let key be Completion(Call(callbackfn, undefined, « value, 𝔽(k) »)).
auto key = call(vm, callback_function, js_undefined(), value, Value(k));
// f. IfAbruptCloseIterator(key, iteratorRecord).
if (key.is_error())
return Completion { TRY(iterator_close(vm, iterator_record, key.release_error())) };
auto key = TRY_OR_CLOSE_ITERATOR(vm, iterator_record, call(vm, callback_function, js_undefined(), value, Value(k)));
// g. If keyCoercion is property, then
if constexpr (IsSame<KeyType, PropertyKey>) {
// i. Set key to Completion(ToPropertyKey(key)).
auto property_key = key.value().to_property_key(vm);
// ii. IfAbruptCloseIterator(key, iteratorRecord).
if (property_key.is_error())
return Completion { TRY(iterator_close(vm, iterator_record, property_key.release_error())) };
auto property_key = TRY_OR_CLOSE_ITERATOR(vm, iterator_record, key.to_property_key(vm));
add_value_to_keyed_group(vm, groups, property_key.release_value(), value);
add_value_to_keyed_group(vm, groups, move(property_key), value);
}
// h. Else,
else {
@ -260,9 +254,9 @@ ThrowCompletionOr<GroupsType> group_by(VM& vm, Value items, Value callback_funct
static_assert(IsSame<KeyType, void>);
// ii. Set key to CanonicalizeKeyedCollectionKey(key).
key = canonicalize_keyed_collection_key(key.value());
key = canonicalize_keyed_collection_key(key);
add_value_to_keyed_group(vm, groups, make_root(key.release_value()), value);
add_value_to_keyed_group(vm, groups, make_root(key), value);
}
// i. Perform AddValueToKeyedGroup(groups, key, value).

View file

@ -214,12 +214,8 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
// v. If mapping is true, then
if (mapfn) {
// 1. Let mappedValue be Completion(Call(mapfn, thisArg, « nextValue, 𝔽(k) »)).
auto mapped_value_or_error = JS::call(vm, *mapfn, this_arg, next.release_value(), Value(k));
// 2. IfAbruptCloseIterator(mappedValue, iteratorRecord).
if (mapped_value_or_error.is_error())
return TRY(iterator_close(vm, iterator, mapped_value_or_error.release_error()));
mapped_value = mapped_value_or_error.release_value();
mapped_value = TRY_OR_CLOSE_ITERATOR(vm, iterator, JS::call(vm, *mapfn, this_arg, next.release_value(), Value(k)));
}
// vi. Else, let mappedValue be nextValue.
else {
@ -227,11 +223,8 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
}
// vii. Let defineStatus be Completion(CreateDataPropertyOrThrow(A, Pk, mappedValue)).
auto result_or_error = array->create_data_property_or_throw(property_key, mapped_value);
// viii. IfAbruptCloseIterator(defineStatus, iteratorRecord).
if (result_or_error.is_error())
return TRY(iterator_close(vm, iterator, result_or_error.release_error()));
TRY_OR_CLOSE_ITERATOR(vm, iterator, array->create_data_property_or_throw(property_key, mapped_value));
// ix. Set k to k + 1.
}

View file

@ -67,6 +67,24 @@ enum class PrimitiveHandling {
RejectPrimitives,
};
// 7.4.12 IfAbruptCloseIterator ( value, iteratorRecord ), https://tc39.es/ecma262/#sec-ifabruptcloseiterator
#define TRY_OR_CLOSE_ITERATOR(vm, iterator_record, expression) \
({ \
auto&& _temporary_try_or_close_result = (expression); \
\
/* 1. Assert: value is a Completion Record. */ \
/* 2. If value is an abrupt completion, return ? IteratorClose(iteratorRecord, value). */ \
if (_temporary_try_or_close_result.is_error()) { \
return iterator_close(vm, iterator_record, _temporary_try_or_close_result.release_error()); \
} \
\
static_assert(!::AK::Detail::IsLvalueReference<decltype(_temporary_try_or_close_result.release_value())>, \
"Do not return a reference from a fallible expression"); \
\
/* 3. Else, set value to ! value. */ \
_temporary_try_or_close_result.release_value(); \
})
ThrowCompletionOr<GC::Ref<IteratorRecord>> get_iterator_direct(VM&, Object&);
ThrowCompletionOr<GC::Ref<IteratorRecord>> get_iterator_from_method(VM&, Value, GC::Ref<FunctionObject>);
ThrowCompletionOr<GC::Ref<IteratorRecord>> get_iterator(VM&, Value, IteratorHint);