summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2022-06-24 00:27:29 +0100
committerLinus Groh <mail@linusgroh.de>2022-06-24 22:12:03 +0100
commitee0d5d6649b3c092aec3bd1b85b5b178a1899410 (patch)
treea5ad46e2d51c1e80a1be97647412ec55b49a5d70 /Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp
parent05c5263eccee4037c59e564dfe0fccc71525b83c (diff)
downloadserenity-ee0d5d6649b3c092aec3bd1b85b5b178a1899410.zip
LibJS: Refactor common option reading into the GetDifferenceSettings AO
This is an editorial change in the Temporal spec. See: https://github.com/tc39/proposal-temporal/commit/78abbb8
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp')
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp60
1 files changed, 59 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp
index 3d2d2919c1..f57717f354 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp
@@ -457,7 +457,7 @@ static Vector<TemporalUnit> temporal_units = {
};
// 13.15 GetTemporalUnit ( normalizedOptions, key, unitGroup, default [ , extraValues ] ), https://tc39.es/proposal-temporal/#sec-temporal-gettemporalunit
-ThrowCompletionOr<Optional<String>> get_temporal_unit(GlobalObject& global_object, Object const& normalized_options, PropertyKey const& key, UnitGroup unit_group, Variant<TemporalUnitRequired, Optional<StringView>> const& default_, Vector<StringView> const& extra_values)
+ThrowCompletionOr<Optional<String>> get_temporal_unit(GlobalObject& global_object, Object const& normalized_options, PropertyKey const& key, UnitGroup unit_group, TemporalUnitDefault const& default_, Vector<StringView> const& extra_values)
{
auto& vm = global_object.vm();
@@ -1838,4 +1838,62 @@ ThrowCompletionOr<Object*> prepare_temporal_fields(GlobalObject& global_object,
return result;
}
+// 13.44 GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits, fallbackSmallestUnit, smallestLargestDefaultUnit ), https://tc39.es/proposal-temporal/#sec-temporal-getdifferencesettings
+ThrowCompletionOr<DifferenceSettings> get_difference_settings(GlobalObject& global_object, DifferenceOperation operation, Value options_value, UnitGroup unit_group, Vector<StringView> const& disallowed_units, TemporalUnitDefault const& fallback_smallest_unit, StringView smallest_largest_default_unit)
+{
+ auto& vm = global_object.vm();
+
+ // 1. Set options to ? GetOptionsObject(options).
+ auto* options = TRY(get_options_object(global_object, options_value));
+
+ // 2. Let smallestUnit be ? GetTemporalUnit(options, "smallestUnit", unitGroup, fallbackSmallestUnit).
+ auto smallest_unit = TRY(get_temporal_unit(global_object, *options, vm.names.smallestUnit, unit_group, fallback_smallest_unit));
+
+ // 3. If disallowedUnits contains smallestUnit, throw a RangeError exception.
+ if (disallowed_units.contains_slow(*smallest_unit))
+ return vm.throw_completion<RangeError>(global_object, ErrorType::OptionIsNotValidValue, *smallest_unit, "smallestUnit"sv);
+
+ // 4. Let defaultLargestUnit be ! LargerOfTwoTemporalUnits(smallestLargestDefaultUnit, smallestUnit).
+ auto default_largest_unit = larger_of_two_temporal_units(smallest_largest_default_unit, *smallest_unit);
+
+ // 5. Let largestUnit be ? GetTemporalUnit(options, "largestUnit", unitGroup, "auto").
+ auto largest_unit = TRY(get_temporal_unit(global_object, *options, vm.names.largestUnit, unit_group, { "auto"sv }));
+
+ // 6. If disallowedUnits contains largestUnit, throw a RangeError exception.
+ if (disallowed_units.contains_slow(*largest_unit))
+ return vm.throw_completion<RangeError>(global_object, ErrorType::OptionIsNotValidValue, *largest_unit, "largestUnit"sv);
+
+ // 7. If largestUnit is "auto", set largestUnit to defaultLargestUnit.
+ if (largest_unit == "auto"sv)
+ largest_unit = default_largest_unit;
+
+ // 8. If LargerOfTwoTemporalUnits(largestUnit, smallestUnit) is not largestUnit, throw a RangeError exception.
+ if (larger_of_two_temporal_units(*largest_unit, *smallest_unit) != largest_unit)
+ return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidUnitRange, *smallest_unit, *largest_unit);
+
+ // 9. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc").
+ auto rounding_mode = TRY(to_temporal_rounding_mode(global_object, *options, "trunc"sv));
+
+ // 10. If operation is since, then
+ if (operation == DifferenceOperation::Since) {
+ // a. Set roundingMode to ! NegateTemporalRoundingMode(roundingMode).
+ rounding_mode = negate_temporal_rounding_mode(rounding_mode);
+ }
+
+ // 11. Let maximum be ! MaximumTemporalDurationRoundingIncrement(smallestUnit).
+ auto maximum = maximum_temporal_duration_rounding_increment(*smallest_unit);
+
+ // 12. Let roundingIncrement be ? ToTemporalRoundingIncrement(options, maximum, false).
+ auto rounding_increment = TRY(to_temporal_rounding_increment(global_object, *options, Optional<double> { maximum }, false));
+
+ // 13. Return the Record { [[SmallestUnit]]: smallestUnit, [[LargestUnit]]: largestUnit, [[RoundingMode]]: roundingMode, [[RoundingIncrement]]: roundingIncrement, [[Options]]: options }.
+ return DifferenceSettings {
+ .smallest_unit = smallest_unit.release_value(),
+ .largest_unit = largest_unit.release_value(),
+ .rounding_mode = move(rounding_mode),
+ .rounding_increment = rounding_increment,
+ .options = *options,
+ };
+}
+
}