diff options
author | Linus Groh <mail@linusgroh.de> | 2022-06-24 00:27:29 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2022-06-24 22:12:03 +0100 |
commit | ee0d5d6649b3c092aec3bd1b85b5b178a1899410 (patch) | |
tree | a5ad46e2d51c1e80a1be97647412ec55b49a5d70 /Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp | |
parent | 05c5263eccee4037c59e564dfe0fccc71525b83c (diff) | |
download | serenity-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.cpp | 60 |
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, + }; +} + } |