mirror of
				https://github.com/LadybirdBrowser/ladybird.git
				synced 2025-10-31 21:30:58 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			246 lines
		
	
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | ||
|  * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
 | ||
|  * Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
 | ||
|  * Copyright (c) 2024-2025, 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/AbstractOperations.h>
 | ||
| #include <LibJS/Runtime/Completion.h>
 | ||
| #include <LibJS/Runtime/Temporal/ISO8601.h>
 | ||
| #include <LibJS/Runtime/Temporal/ISORecords.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 Direction {
 | ||
|     Next,
 | ||
|     Previous,
 | ||
| };
 | ||
| 
 | ||
| enum class Disambiguation {
 | ||
|     Compatible,
 | ||
|     Earlier,
 | ||
|     Later,
 | ||
|     Reject,
 | ||
| };
 | ||
| 
 | ||
| enum class DurationOperation {
 | ||
|     Since,
 | ||
|     Until,
 | ||
| };
 | ||
| 
 | ||
| enum class OffsetOption {
 | ||
|     Prefer,
 | ||
|     Use,
 | ||
|     Ignore,
 | ||
|     Reject,
 | ||
| };
 | ||
| 
 | ||
| enum class Overflow {
 | ||
|     Constrain,
 | ||
|     Reject,
 | ||
| };
 | ||
| 
 | ||
| enum class ShowCalendar {
 | ||
|     Auto,
 | ||
|     Always,
 | ||
|     Never,
 | ||
|     Critical,
 | ||
| };
 | ||
| 
 | ||
| enum class ShowOffset {
 | ||
|     Auto,
 | ||
|     Never,
 | ||
| };
 | ||
| 
 | ||
| enum class ShowTimeZoneName {
 | ||
|     Auto,
 | ||
|     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,
 | ||
| };
 | ||
| JS_API 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 UnsignedRoundingMode {
 | ||
|     HalfEven,
 | ||
|     HalfInfinity,
 | ||
|     HalfZero,
 | ||
|     Infinity,
 | ||
|     Zero,
 | ||
| };
 | ||
| 
 | ||
| // https://tc39.es/proposal-temporal/#table-unsigned-rounding-modes
 | ||
| enum class Sign {
 | ||
|     Negative,
 | ||
|     Positive,
 | ||
| };
 | ||
| 
 | ||
| struct Auto { };
 | ||
| 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 {
 | ||
|     GC::Ptr<PlainDate> plain_relative_to;     // [[PlainRelativeTo]]
 | ||
|     GC::Ptr<ZonedDateTime> zoned_relative_to; // [[ZonedRelativeTo]]
 | ||
| };
 | ||
| 
 | ||
| struct DifferenceSettings {
 | ||
|     Unit smallest_unit;
 | ||
|     Unit largest_unit;
 | ||
|     RoundingMode rounding_mode;
 | ||
|     u64 rounding_increment { 0 };
 | ||
| };
 | ||
| 
 | ||
| JS_API double iso_date_to_epoch_days(double year, double month, double date);
 | ||
| JS_API double epoch_days_to_epoch_ms(double day, double time);
 | ||
| JS_API ThrowCompletionOr<void> check_iso_days_range(VM&, ISODate);
 | ||
| JS_API ThrowCompletionOr<Overflow> get_temporal_overflow_option(VM&, Object const& options);
 | ||
| JS_API ThrowCompletionOr<Disambiguation> get_temporal_disambiguation_option(VM&, Object const& options);
 | ||
| JS_API RoundingMode negate_rounding_mode(RoundingMode);
 | ||
| JS_API ThrowCompletionOr<OffsetOption> get_temporal_offset_option(VM&, Object const& options, OffsetOption fallback);
 | ||
| JS_API ThrowCompletionOr<ShowTimeZoneName> get_temporal_show_time_zone_name_option(VM&, Object const& options);
 | ||
| JS_API ThrowCompletionOr<ShowOffset> get_temporal_show_offset_option(VM&, Object const& options);
 | ||
| JS_API ThrowCompletionOr<ShowCalendar> get_temporal_show_calendar_name_option(VM&, Object const& options);
 | ||
| JS_API ThrowCompletionOr<Direction> get_direction_option(VM&, Object const& options);
 | ||
| JS_API ThrowCompletionOr<void> validate_temporal_rounding_increment(VM&, u64 increment, u64 dividend, bool inclusive);
 | ||
| JS_API ThrowCompletionOr<Precision> get_temporal_fractional_second_digits_option(VM&, Object const& options);
 | ||
| JS_API SecondsStringPrecision to_seconds_string_precision_record(UnitValue, Precision);
 | ||
| JS_API ThrowCompletionOr<UnitValue> get_temporal_unit_valued_option(VM&, Object const& options, PropertyKey const&, UnitGroup, UnitDefault const&, ReadonlySpan<UnitValue> extra_values = {});
 | ||
| JS_API ThrowCompletionOr<RelativeTo> get_temporal_relative_to_option(VM&, Object const& options);
 | ||
| JS_API Unit larger_of_two_temporal_units(Unit, Unit);
 | ||
| JS_API bool is_calendar_unit(Unit);
 | ||
| JS_API UnitCategory temporal_unit_category(Unit);
 | ||
| JS_API RoundingIncrement maximum_temporal_duration_rounding_increment(Unit);
 | ||
| JS_API Crypto::UnsignedBigInteger const& temporal_unit_length_in_nanoseconds(Unit);
 | ||
| JS_API ThrowCompletionOr<bool> is_partial_temporal_object(VM&, Value);
 | ||
| JS_API String format_fractional_seconds(u64, Precision);
 | ||
| JS_API String format_time_string(u8 hour, u8 minute, u8 second, u64 sub_second_nanoseconds, SecondsStringPrecision::Precision, Optional<TimeStyle> = {});
 | ||
| JS_API UnsignedRoundingMode get_unsigned_rounding_mode(RoundingMode, Sign);
 | ||
| JS_API double apply_unsigned_rounding_mode(double, double r1, double r2, UnsignedRoundingMode);
 | ||
| JS_API Crypto::SignedBigInteger apply_unsigned_rounding_mode(Crypto::SignedDivisionResult const&, Crypto::SignedBigInteger r1, Crypto::SignedBigInteger r2, UnsignedRoundingMode, Crypto::UnsignedBigInteger const& increment);
 | ||
| JS_API double round_number_to_increment(double, u64 increment, RoundingMode);
 | ||
| JS_API Crypto::SignedBigInteger round_number_to_increment(Crypto::SignedBigInteger const&, Crypto::UnsignedBigInteger const& increment, RoundingMode);
 | ||
| JS_API Crypto::SignedBigInteger round_number_to_increment_as_if_positive(Crypto::SignedBigInteger const&, Crypto::UnsignedBigInteger const& increment, RoundingMode);
 | ||
| JS_API ThrowCompletionOr<ParsedISODateTime> parse_iso_date_time(VM&, StringView iso_string, ReadonlySpan<Production> allowed_formats);
 | ||
| JS_API ThrowCompletionOr<String> parse_temporal_calendar_string(VM&, String const&);
 | ||
| JS_API ThrowCompletionOr<GC::Ref<Duration>> parse_temporal_duration_string(VM&, StringView iso_string);
 | ||
| JS_API ThrowCompletionOr<TimeZone> parse_temporal_time_zone_string(VM&, StringView time_zone_string);
 | ||
| JS_API ThrowCompletionOr<String> to_month_code(VM&, Value argument);
 | ||
| JS_API ThrowCompletionOr<String> to_offset_string(VM&, Value argument);
 | ||
| JS_API CalendarFields iso_date_to_fields(StringView calendar, ISODate, DateType);
 | ||
| JS_API ThrowCompletionOr<DifferenceSettings> get_difference_settings(VM&, DurationOperation, Object const& options, UnitGroup, ReadonlySpan<Unit> disallowed_units, Unit fallback_smallest_unit, Unit smallest_largest_default_unit);
 | ||
| 
 | ||
| // 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;
 | ||
| }
 | ||
| 
 | ||
| }
 | 
