123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- /*
- * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
- * Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
- * Copyright (c) 2024, Tim Flynn <trflynn89@ladybird.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #pragma once
- #include <AK/Variant.h>
- #include <LibCrypto/BigInt/SignedBigInteger.h>
- #include <LibCrypto/BigInt/UnsignedBigInteger.h>
- #include <LibGC/Ptr.h>
- #include <LibJS/Forward.h>
- #include <LibJS/Runtime/Completion.h>
- #include <LibJS/Runtime/Temporal/ISO8601.h>
- #include <LibJS/Runtime/Temporal/PlainTime.h>
- #include <LibJS/Runtime/VM.h>
- #include <LibJS/Runtime/ValueInlines.h>
- #include <math.h>
- namespace JS::Temporal {
- enum class ArithmeticOperation {
- Add,
- Subtract,
- };
- enum class DateType {
- Date,
- MonthDay,
- YearMonth,
- };
- enum class Overflow {
- Constrain,
- Reject,
- };
- enum class ShowCalendar {
- Auto,
- Always,
- Never,
- Critical,
- };
- enum class TimeStyle {
- Separated,
- Unseparated,
- };
- // https://tc39.es/proposal-temporal/#sec-temporal-units
- enum class Unit {
- Year,
- Month,
- Week,
- Day,
- Hour,
- Minute,
- Second,
- Millisecond,
- Microsecond,
- Nanosecond,
- };
- StringView temporal_unit_to_string(Unit);
- // https://tc39.es/proposal-temporal/#sec-temporal-units
- enum class UnitCategory {
- Date,
- Time,
- };
- // https://tc39.es/proposal-temporal/#sec-temporal-units
- enum class UnitGroup {
- Date,
- Time,
- DateTime,
- };
- // https://tc39.es/proposal-temporal/#table-unsigned-rounding-modes
- enum class RoundingMode {
- Ceil,
- Floor,
- Expand,
- Trunc,
- HalfCeil,
- HalfFloor,
- HalfExpand,
- HalfTrunc,
- HalfEven,
- };
- // https://tc39.es/proposal-temporal/#table-unsigned-rounding-modes
- enum class UnsignedRoundingMode {
- HalfEven,
- HalfInfinity,
- HalfZero,
- Infinity,
- Zero,
- };
- // https://tc39.es/proposal-temporal/#table-unsigned-rounding-modes
- enum class Sign {
- Negative,
- Positive,
- };
- struct Auto { };
- struct Required { };
- struct Unset { };
- using Precision = Variant<Auto, u8>;
- using RoundingIncrement = Variant<Unset, u64>;
- using UnitDefault = Variant<Required, Unset, Auto, Unit>;
- using UnitValue = Variant<Unset, Auto, Unit>;
- struct SecondsStringPrecision {
- struct Minute { };
- using Precision = Variant<Minute, Auto, u8>;
- Precision precision;
- Unit unit;
- u8 increment { 0 };
- };
- struct RelativeTo {
- // FIXME: Make these objects represent their actual types when we re-implement them.
- GC::Ptr<JS::Object> plain_relative_to; // [[PlainRelativeTo]]
- GC::Ptr<JS::Object> zoned_relative_to; // [[ZonedRelativeTo]]
- };
- // 13.31 ISO String Time Zone Parse Records, https://tc39.es/proposal-temporal/#sec-temporal-iso-string-time-zone-parse-records
- struct ParsedISOTimeZone {
- bool z_designator { false };
- Optional<String> offset_string;
- Optional<String> time_zone_annotation;
- };
- // 13.32 ISO Date-Time Parse Records, https://tc39.es/proposal-temporal/#sec-temporal-iso-date-time-parse-records
- struct ParsedISODateTime {
- struct StartOfDay { };
- Optional<i32> year { 0 };
- u8 month { 0 };
- u8 day { 0 };
- Variant<StartOfDay, Time> time;
- ParsedISOTimeZone time_zone;
- Optional<String> calendar;
- };
- double iso_date_to_epoch_days(double year, double month, double date);
- double epoch_days_to_epoch_ms(double day, double time);
- ThrowCompletionOr<Overflow> get_temporal_overflow_option(VM&, Object const& options);
- ThrowCompletionOr<ShowCalendar> get_temporal_show_calendar_name_option(VM&, Object const& options);
- ThrowCompletionOr<void> validate_temporal_rounding_increment(VM&, u64 increment, u64 dividend, bool inclusive);
- ThrowCompletionOr<Precision> get_temporal_fractional_second_digits_option(VM&, Object const& options);
- SecondsStringPrecision to_seconds_string_precision_record(UnitValue, Precision);
- ThrowCompletionOr<UnitValue> get_temporal_unit_valued_option(VM&, Object const& options, PropertyKey const&, UnitGroup, UnitDefault const&, ReadonlySpan<UnitValue> extra_values = {});
- ThrowCompletionOr<RelativeTo> get_temporal_relative_to_option(VM&, Object const& options);
- Unit larger_of_two_temporal_units(Unit, Unit);
- bool is_calendar_unit(Unit);
- UnitCategory temporal_unit_category(Unit);
- RoundingIncrement maximum_temporal_duration_rounding_increment(Unit);
- Crypto::UnsignedBigInteger const& temporal_unit_length_in_nanoseconds(Unit);
- ThrowCompletionOr<bool> is_partial_temporal_object(VM&, Value);
- String format_fractional_seconds(u64, Precision);
- String format_time_string(u8 hour, u8 minute, u8 second, u16 sub_second_nanoseconds, SecondsStringPrecision::Precision, Optional<TimeStyle> = {});
- UnsignedRoundingMode get_unsigned_rounding_mode(RoundingMode, Sign);
- double apply_unsigned_rounding_mode(double, double r1, double r2, UnsignedRoundingMode);
- Crypto::SignedBigInteger apply_unsigned_rounding_mode(Crypto::SignedDivisionResult const&, Crypto::SignedBigInteger const& r1, Crypto::SignedBigInteger const& r2, UnsignedRoundingMode, Crypto::UnsignedBigInteger const& increment);
- double round_number_to_increment(double, u64 increment, RoundingMode);
- Crypto::SignedBigInteger round_number_to_increment(Crypto::SignedBigInteger const&, Crypto::UnsignedBigInteger const& increment, RoundingMode);
- ThrowCompletionOr<ParsedISODateTime> parse_iso_date_time(VM&, StringView iso_string, ReadonlySpan<Production> allowed_formats);
- ThrowCompletionOr<String> parse_temporal_calendar_string(VM&, String const&);
- ThrowCompletionOr<GC::Ref<Duration>> parse_temporal_duration_string(VM&, StringView iso_string);
- ThrowCompletionOr<TimeZone> parse_temporal_time_zone_string(VM& vm, StringView time_zone_string);
- ThrowCompletionOr<String> to_month_code(VM&, Value argument);
- ThrowCompletionOr<String> to_offset_string(VM&, Value argument);
- CalendarFields iso_date_to_fields(StringView calendar, ISODate const&, DateType);
- // 13.38 ToIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerwithtruncation
- template<typename... Args>
- ThrowCompletionOr<double> to_integer_with_truncation(VM& vm, Value argument, ErrorType error_type, Args&&... args)
- {
- // 1. Let number be ? ToNumber(argument).
- auto number = TRY(argument.to_number(vm));
- // 2. If number is NaN, +∞𝔽 or -∞𝔽, throw a RangeError exception.
- if (number.is_nan() || number.is_infinity())
- return vm.throw_completion<RangeError>(error_type, forward<Args>(args)...);
- // 3. Return truncate(ℝ(number)).
- return trunc(number.as_double());
- }
- // 13.38 ToIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerwithtruncation
- // AD-HOC: We often need to use this AO when we have a parsed StringView. This overload allows callers to avoid creating
- // a PrimitiveString for the primary definition.
- template<typename... Args>
- ThrowCompletionOr<double> to_integer_with_truncation(VM& vm, StringView argument, ErrorType error_type, Args&&... args)
- {
- // 1. Let number be ? ToNumber(argument).
- auto number = string_to_number(argument);
- // 2. If number is NaN, +∞𝔽 or -∞𝔽, throw a RangeError exception.
- if (isnan(number) || isinf(number))
- return vm.throw_completion<RangeError>(error_type, forward<Args>(args)...);
- // 3. Return truncate(ℝ(number)).
- return trunc(number);
- }
- // 13.37 ToPositiveIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-topositiveintegerwithtruncation
- template<typename... Args>
- ThrowCompletionOr<double> to_positive_integer_with_truncation(VM& vm, Value argument, ErrorType error_type, Args&&... args)
- {
- // 1. Let integer be ? ToIntegerWithTruncation(argument).
- auto integer = TRY(to_integer_with_truncation(vm, argument, error_type, args...));
- // 2. If integer ≤ 0, throw a RangeError exception.
- if (integer <= 0)
- return vm.throw_completion<RangeError>(error_type, args...);
- // 3. Return integer.
- return integer;
- }
- // 13.39 ToIntegerIfIntegral ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerifintegral
- template<typename... Args>
- ThrowCompletionOr<double> to_integer_if_integral(VM& vm, Value argument, ErrorType error_type, Args&&... args)
- {
- // 1. Let number be ? ToNumber(argument).
- auto number = TRY(argument.to_number(vm));
- // 2. If number is not an integral Number, throw a RangeError exception.
- if (!number.is_integral_number())
- return vm.throw_completion<RangeError>(error_type, forward<Args>(args)...);
- // 3. Return ℝ(number).
- return number.as_double();
- }
- // 14.2 The Year-Week Record Specification Type, https://tc39.es/proposal-temporal/#sec-year-week-record-specification-type
- struct YearWeek {
- Optional<u8> week;
- Optional<i32> year;
- };
- enum class OptionType {
- Boolean,
- String,
- };
- using OptionDefault = Variant<Required, Empty, bool, StringView, double>;
- ThrowCompletionOr<GC::Ref<Object>> get_options_object(VM&, Value options);
- ThrowCompletionOr<Value> get_option(VM&, Object const& options, PropertyKey const& property, OptionType type, ReadonlySpan<StringView> values, OptionDefault const&);
- template<size_t Size>
- ThrowCompletionOr<Value> get_option(VM& vm, Object const& options, PropertyKey const& property, OptionType type, StringView const (&values)[Size], OptionDefault const& default_)
- {
- return get_option(vm, options, property, type, ReadonlySpan<StringView> { values }, default_);
- }
- ThrowCompletionOr<RoundingMode> get_rounding_mode_option(VM&, Object const& options, RoundingMode fallback);
- ThrowCompletionOr<u64> get_rounding_increment_option(VM&, Object const& options);
- Crypto::SignedBigInteger get_utc_epoch_nanoseconds(ISODateTime const&);
- }
|