1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 22:57:44 +00:00

LibJS: Implement the ToTemporalDate Abstract Operation

This is required by most Temporal.PlainDate.prototype methods.
This commit is contained in:
Idan Horowitz 2021-07-21 22:20:57 +03:00 committed by Linus Groh
parent 1e471e2e2f
commit cf78efaef5
7 changed files with 245 additions and 11 deletions

View file

@ -7,6 +7,7 @@
#include <AK/CharacterTypes.h>
#include <AK/DateTimeLexer.h>
#include <LibJS/Runtime/IteratorOperations.h>
#include <LibJS/Runtime/Temporal/AbstractOperations.h>
#include <LibJS/Runtime/Temporal/Duration.h>
#include <LibJS/Runtime/Temporal/PlainDate.h>
@ -15,6 +16,64 @@
namespace JS::Temporal {
static Optional<OptionType> to_option_type(Value value)
{
if (value.is_boolean())
return OptionType::Boolean;
if (value.is_string())
return OptionType::String;
if (value.is_number())
return OptionType::Number;
return {};
}
// 13.1 IterableToListOfType ( items, elementTypes ), https://tc39.es/proposal-temporal/#sec-iterabletolistoftype
MarkedValueList iterable_to_list_of_type(GlobalObject& global_object, Value items, Vector<OptionType> const& element_types)
{
auto& vm = global_object.vm();
auto& heap = global_object.heap();
// 1. Let iteratorRecord be ? GetIterator(items, sync).
auto iterator_record = get_iterator(global_object, items, IteratorHint::Sync);
if (vm.exception())
return MarkedValueList { heap };
// 2. Let values be a new empty List.
MarkedValueList values(heap);
// 3. Let next be true.
auto next = true;
// 4. Repeat, while next is not false,
while (next) {
// a. Set next to ? IteratorStep(iteratorRecord).
auto* iterator_result = iterator_step(global_object, *iterator_record);
if (vm.exception())
return MarkedValueList { heap };
next = iterator_result;
// b. If next is not false, then
if (next) {
// i. Let nextValue be ? IteratorValue(next).
auto next_value = iterator_value(global_object, *iterator_result);
if (vm.exception())
return MarkedValueList { heap };
// ii. If Type(nextValue) is not an element of elementTypes, then
if (auto type = to_option_type(next_value); !type.has_value() || !element_types.contains_slow(*type)) {
// 1. Let completion be ThrowCompletion(a newly created TypeError object).
vm.throw_exception<TypeError>(global_object, ErrorType::FixmeAddAnErrorString);
// 2. Return ? IteratorClose(iteratorRecord, completion).
iterator_close(*iterator_record);
return MarkedValueList { heap };
}
// iii. Append nextValue to the end of the List values.
values.append(next_value);
}
}
// 5. Return values.
return values;
}
// 13.2 GetOptionsObject ( options ), https://tc39.es/proposal-temporal/#sec-getoptionsobject
Object* get_options_object(GlobalObject& global_object, Value options)
{
@ -37,17 +96,6 @@ Object* get_options_object(GlobalObject& global_object, Value options)
return {};
}
static Optional<OptionType> to_option_type(Value value)
{
if (value.is_boolean())
return OptionType::Boolean;
if (value.is_string())
return OptionType::String;
if (value.is_number())
return OptionType::Number;
return {};
}
// 13.3 GetOption ( options, property, types, values, fallback ), https://tc39.es/proposal-temporal/#sec-getoption
Value get_option(GlobalObject& global_object, Object& options, String const& property, Vector<OptionType> const& types, Vector<StringView> const& values, Value fallback)
{
@ -464,6 +512,26 @@ Optional<String> parse_temporal_calendar_string([[maybe_unused]] GlobalObject& g
return id_part.value();
}
// 13.38 ParseTemporalDateString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaldatestring
Optional<TemporalDate> parse_temporal_date_string(GlobalObject& global_object, String const& iso_string)
{
auto& vm = global_object.vm();
// 1. Assert: Type(isoString) is String.
// 2. If isoString does not satisfy the syntax of a TemporalDateString (see 13.33), then
// a. Throw a RangeError exception.
// TODO
// 3. Let result be ? ParseISODateTime(isoString).
auto result = parse_iso_date_time(global_object, iso_string);
if (vm.exception())
return {};
// 4. Return the new Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }.
return TemporalDate { .year = result->year, .month = result->month, .day = result->day, .calendar = move(result->calendar) };
}
// 13.40 ParseTemporalDurationString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaldurationstring
Optional<TemporalDuration> parse_temporal_duration_string(GlobalObject& global_object, String const& iso_string)
{