mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-06-09 17:44:56 +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:
parent
568524f8ba
commit
908349f8fe
Notes:
github-actions[bot]
2025-04-29 11:34:16 +00:00
Author: https://github.com/trflynn89
Commit: 908349f8fe
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4514
3 changed files with 25 additions and 20 deletions
|
@ -237,22 +237,16 @@ ThrowCompletionOr<GroupsType> group_by(VM& vm, Value items, Value callback_funct
|
||||||
auto value = next.release_value();
|
auto value = next.release_value();
|
||||||
|
|
||||||
// e. Let key be Completion(Call(callbackfn, undefined, « value, 𝔽(k) »)).
|
// 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).
|
// f. IfAbruptCloseIterator(key, iteratorRecord).
|
||||||
if (key.is_error())
|
auto key = TRY_OR_CLOSE_ITERATOR(vm, iterator_record, call(vm, callback_function, js_undefined(), value, Value(k)));
|
||||||
return Completion { TRY(iterator_close(vm, iterator_record, key.release_error())) };
|
|
||||||
|
|
||||||
// g. If keyCoercion is property, then
|
// g. If keyCoercion is property, then
|
||||||
if constexpr (IsSame<KeyType, PropertyKey>) {
|
if constexpr (IsSame<KeyType, PropertyKey>) {
|
||||||
// i. Set key to Completion(ToPropertyKey(key)).
|
// i. Set key to Completion(ToPropertyKey(key)).
|
||||||
auto property_key = key.value().to_property_key(vm);
|
|
||||||
|
|
||||||
// ii. IfAbruptCloseIterator(key, iteratorRecord).
|
// ii. IfAbruptCloseIterator(key, iteratorRecord).
|
||||||
if (property_key.is_error())
|
auto property_key = TRY_OR_CLOSE_ITERATOR(vm, iterator_record, key.to_property_key(vm));
|
||||||
return Completion { TRY(iterator_close(vm, iterator_record, property_key.release_error())) };
|
|
||||||
|
|
||||||
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,
|
// h. Else,
|
||||||
else {
|
else {
|
||||||
|
@ -260,9 +254,9 @@ ThrowCompletionOr<GroupsType> group_by(VM& vm, Value items, Value callback_funct
|
||||||
static_assert(IsSame<KeyType, void>);
|
static_assert(IsSame<KeyType, void>);
|
||||||
|
|
||||||
// ii. Set key to CanonicalizeKeyedCollectionKey(key).
|
// 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).
|
// i. Perform AddValueToKeyedGroup(groups, key, value).
|
||||||
|
|
|
@ -214,12 +214,8 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
|
||||||
// v. If mapping is true, then
|
// v. If mapping is true, then
|
||||||
if (mapfn) {
|
if (mapfn) {
|
||||||
// 1. Let mappedValue be Completion(Call(mapfn, thisArg, « nextValue, 𝔽(k) »)).
|
// 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).
|
// 2. IfAbruptCloseIterator(mappedValue, iteratorRecord).
|
||||||
if (mapped_value_or_error.is_error())
|
mapped_value = TRY_OR_CLOSE_ITERATOR(vm, iterator, JS::call(vm, *mapfn, this_arg, next.release_value(), Value(k)));
|
||||||
return TRY(iterator_close(vm, iterator, mapped_value_or_error.release_error()));
|
|
||||||
mapped_value = mapped_value_or_error.release_value();
|
|
||||||
}
|
}
|
||||||
// vi. Else, let mappedValue be nextValue.
|
// vi. Else, let mappedValue be nextValue.
|
||||||
else {
|
else {
|
||||||
|
@ -227,11 +223,8 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
// vii. Let defineStatus be Completion(CreateDataPropertyOrThrow(A, Pk, mappedValue)).
|
// 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).
|
// viii. IfAbruptCloseIterator(defineStatus, iteratorRecord).
|
||||||
if (result_or_error.is_error())
|
TRY_OR_CLOSE_ITERATOR(vm, iterator, array->create_data_property_or_throw(property_key, mapped_value));
|
||||||
return TRY(iterator_close(vm, iterator, result_or_error.release_error()));
|
|
||||||
|
|
||||||
// ix. Set k to k + 1.
|
// ix. Set k to k + 1.
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,24 @@ enum class PrimitiveHandling {
|
||||||
RejectPrimitives,
|
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_direct(VM&, Object&);
|
||||||
ThrowCompletionOr<GC::Ref<IteratorRecord>> get_iterator_from_method(VM&, Value, GC::Ref<FunctionObject>);
|
ThrowCompletionOr<GC::Ref<IteratorRecord>> get_iterator_from_method(VM&, Value, GC::Ref<FunctionObject>);
|
||||||
ThrowCompletionOr<GC::Ref<IteratorRecord>> get_iterator(VM&, Value, IteratorHint);
|
ThrowCompletionOr<GC::Ref<IteratorRecord>> get_iterator(VM&, Value, IteratorHint);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue