From a8d6e5c3db298652e3852d1afa4f929874bb148e Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Fri, 28 Feb 2025 12:15:49 -0500 Subject: [PATCH] LibJS: Migrate Temporal updates to ECMA-262 AOs to the main AO file These are going to be included in the ECMA-262 AOs once Temporal reaches stage 4. There's no need to keep them in the Temporal namespace. Some upcoming Temporal editorial changes will get awkward without this patch. --- .../LibJS/Runtime/AbstractOperations.cpp | 124 +++++++++++++++++ Libraries/LibJS/Runtime/AbstractOperations.h | 70 ++++++---- .../LibJS/Runtime/Intl/AbstractOperations.cpp | 3 +- .../LibJS/Runtime/Intl/AbstractOperations.h | 8 +- .../LibJS/Runtime/Intl/DateTimeFormat.cpp | 2 +- .../Runtime/Intl/DisplayNamesConstructor.cpp | 5 +- .../Intl/DurationFormatConstructor.cpp | 2 +- .../Runtime/Intl/ListFormatConstructor.cpp | 3 +- Libraries/LibJS/Runtime/Intl/PluralRules.cpp | 1 + .../Runtime/Intl/SegmenterConstructor.cpp | 3 +- .../Runtime/Temporal/AbstractOperations.cpp | 126 +----------------- .../Runtime/Temporal/AbstractOperations.h | 44 +----- Libraries/LibJS/Runtime/Uint8Array.cpp | 10 +- 13 files changed, 183 insertions(+), 218 deletions(-) diff --git a/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Libraries/LibJS/Runtime/AbstractOperations.cpp index 4820c99e0e5..aca91c05c69 100644 --- a/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include namespace JS { @@ -1810,4 +1811,127 @@ ThrowCompletionOr perform_import_call(VM& vm, Value specifier, Value opti return Value { promise_capability->promise() }; } +// 14.5.2.1 GetOptionsObject ( options ), https://tc39.es/proposal-temporal/#sec-getoptionsobject +ThrowCompletionOr> get_options_object(VM& vm, Value options) +{ + auto& realm = *vm.current_realm(); + + // 1. If options is undefined, then + if (options.is_undefined()) { + // a. Return OrdinaryObjectCreate(null). + return Object::create(realm, nullptr); + } + + // 2. If options is an Object, then + if (options.is_object()) { + // a. Return options. + return options.as_object(); + } + + // 3. Throw a TypeError exception. + return vm.throw_completion(ErrorType::NotAnObject, "Options"); +} + +// 14.5.2.2 GetOption ( options, property, type, values, default ), https://tc39.es/proposal-temporal/#sec-getoption +ThrowCompletionOr get_option(VM& vm, Object const& options, PropertyKey const& property, OptionType type, ReadonlySpan values, OptionDefault const& default_) +{ + VERIFY(property.is_string()); + + // 1. Let value be ? Get(options, property). + auto value = TRY(options.get(property)); + + // 2. If value is undefined, then + if (value.is_undefined()) { + // a. If default is REQUIRED, throw a RangeError exception. + if (default_.has()) + return vm.throw_completion(ErrorType::OptionIsNotValidValue, "undefined"sv, property.as_string()); + + // b. Return default. + return default_.visit( + [](Required) -> Value { VERIFY_NOT_REACHED(); }, + [](Empty) -> Value { return js_undefined(); }, + [](bool default_) -> Value { return Value { default_ }; }, + [](double default_) -> Value { return Value { default_ }; }, + [&](StringView default_) -> Value { return PrimitiveString::create(vm, default_); }); + } + + // 3. If type is BOOLEAN, then + if (type == OptionType::Boolean) { + // a. Set value to ToBoolean(value). + value = Value { value.to_boolean() }; + } + // 4. Else, + else { + // a. Assert: type is STRING. + VERIFY(type == OptionType::String); + + // b. Set value to ? ToString(value). + value = TRY(value.to_primitive_string(vm)); + } + + // 5. If values is not EMPTY and values does not contain value, throw a RangeError exception. + if (!values.is_empty()) { + // NOTE: Every location in the spec that invokes GetOption with type=boolean also has values=undefined. + VERIFY(value.is_string()); + + if (auto value_string = value.as_string().utf8_string(); !values.contains_slow(value_string)) + return vm.throw_completion(ErrorType::OptionIsNotValidValue, value_string, property.as_string()); + } + + // 6. Return value. + return value; +} + +// 14.5.2.3 GetRoundingModeOption ( options, fallback ), https://tc39.es/proposal-temporal/#sec-temporal-getroundingmodeoption +ThrowCompletionOr get_rounding_mode_option(VM& vm, Object const& options, RoundingMode fallback) +{ + // 1. Let allowedStrings be the List of Strings from the "String Identifier" column of Table 26. + static constexpr auto allowed_strings = to_array({ "ceil"sv, "floor"sv, "expand"sv, "trunc"sv, "halfCeil"sv, "halfFloor"sv, "halfExpand"sv, "halfTrunc"sv, "halfEven"sv }); + + // 2. Let stringFallback be the value from the "String Identifier" column of the row with fallback in its "Rounding Mode" column. + auto string_fallback = allowed_strings[to_underlying(fallback)]; + + // 3. Let stringValue be ? GetOption(options, "roundingMode", STRING, allowedStrings, stringFallback). + auto string_value = TRY(get_option(vm, options, vm.names.roundingMode, OptionType::String, allowed_strings, string_fallback)); + + // 4. Return the value from the "Rounding Mode" column of the row with stringValue in its "String Identifier" column. + return static_cast(allowed_strings.first_index_of(string_value.as_string().utf8_string_view()).value()); +} + +// 14.5.2.4 GetRoundingIncrementOption ( options ), https://tc39.es/proposal-temporal/#sec-temporal-getroundingincrementoption +ThrowCompletionOr get_rounding_increment_option(VM& vm, Object const& options) +{ + // 1. Let value be ? Get(options, "roundingIncrement"). + auto value = TRY(options.get(vm.names.roundingIncrement)); + + // 2. If value is undefined, return 1𝔽. + if (value.is_undefined()) + return 1; + + // 3. Let integerIncrement be ? ToIntegerWithTruncation(value). + auto integer_increment = TRY(Temporal::to_integer_with_truncation(vm, value, ErrorType::OptionIsNotValidValue, value, "roundingIncrement"sv)); + + // 4. If integerIncrement < 1 or integerIncrement > 10**9, throw a RangeError exception. + if (integer_increment < 1 || integer_increment > 1'000'000'000u) + return vm.throw_completion(ErrorType::OptionIsNotValidValue, value, "roundingIncrement"); + + // 5. Return integerIncrement. + return static_cast(integer_increment); +} + +// AD-HOC +// FIXME: We should add a generic floor() method to our BigInt classes. But for now, since we know we are only dividing +// by powers of 10, we can implement a very situationally specific method to compute the floor of a division. +Crypto::SignedBigInteger big_floor(Crypto::SignedBigInteger const& numerator, Crypto::UnsignedBigInteger const& denominator) +{ + auto result = numerator.divided_by(denominator); + + if (result.remainder.is_zero()) + return result.quotient; + if (!result.quotient.is_negative() && result.remainder.is_positive()) + return result.quotient; + + return result.quotient.minus(Crypto::SignedBigInteger { 1 }); +} + } diff --git a/Libraries/LibJS/Runtime/AbstractOperations.h b/Libraries/LibJS/Runtime/AbstractOperations.h index 7149902dbd9..e4f0740eebb 100644 --- a/Libraries/LibJS/Runtime/AbstractOperations.h +++ b/Libraries/LibJS/Runtime/AbstractOperations.h @@ -163,35 +163,6 @@ ThrowCompletionOr> ordinary_create_from_constructor(VM& vm, FunctionO return realm.create(forward(args)..., *prototype); } -// 14.1 MergeLists ( a, b ), https://tc39.es/proposal-temporal/#sec-temporal-mergelists -template -Vector merge_lists(Vector const& a, Vector const& b) -{ - // 1. Let merged be a new empty List. - Vector merged; - - // 2. For each element element of a, do - for (auto const& element : a) { - // a. If merged does not contain element, then - if (!merged.contains_slow(element)) { - // i. Append element to merged. - merged.append(element); - } - } - - // 3. For each element element of b, do - for (auto const& element : b) { - // a. If merged does not contain element, then - if (!merged.contains_slow(element)) { - // i. Append element to merged. - merged.append(element); - } - } - - // 4. Return merged. - return merged; -} - // 7.3.35 AddValueToKeyedGroup ( groups, key, value ), https://tc39.es/ecma262/#sec-add-value-to-keyed-group template void add_value_to_keyed_group(VM& vm, GroupsType& groups, KeyType key, Value value) @@ -348,4 +319,45 @@ auto remainder(Crypto::BigInteger auto const& x, Crypto::BigInteger auto const& return x.divided_by(y).remainder; } +// 14.3 The Year-Week Record Specification Type, https://tc39.es/proposal-temporal/#sec-year-week-record-specification-type +struct YearWeek { + Optional week; + Optional year; +}; + +enum class OptionType { + Boolean, + String, +}; + +struct Required { }; +using OptionDefault = Variant; + +ThrowCompletionOr> get_options_object(VM&, Value options); +ThrowCompletionOr get_option(VM&, Object const& options, PropertyKey const& property, OptionType type, ReadonlySpan values, OptionDefault const&); + +template +ThrowCompletionOr 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 { values }, default_); +} + +// https://tc39.es/proposal-temporal/#table-temporal-rounding-modes +enum class RoundingMode { + Ceil, + Floor, + Expand, + Trunc, + HalfCeil, + HalfFloor, + HalfExpand, + HalfTrunc, + HalfEven, +}; + +ThrowCompletionOr get_rounding_mode_option(VM&, Object const& options, RoundingMode fallback); +ThrowCompletionOr get_rounding_increment_option(VM&, Object const& options); + +Crypto::SignedBigInteger big_floor(Crypto::SignedBigInteger const& numerator, Crypto::UnsignedBigInteger const& denominator); + } diff --git a/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp b/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp index 5120a3effb4..166f7a84c94 100644 --- a/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp +++ b/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024, Tim Flynn + * Copyright (c) 2021-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff --git a/Libraries/LibJS/Runtime/Intl/AbstractOperations.h b/Libraries/LibJS/Runtime/Intl/AbstractOperations.h index 2f595c252f3..14adeabceb7 100644 --- a/Libraries/LibJS/Runtime/Intl/AbstractOperations.h +++ b/Libraries/LibJS/Runtime/Intl/AbstractOperations.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024, Tim Flynn + * Copyright (c) 2021-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -72,9 +71,4 @@ ThrowCompletionOr get_boolean_or_string_number_format_option(VM return get_boolean_or_string_number_format_option(vm, options, property, ReadonlySpan { string_values }, move(fallback)); } -// NOTE: ECMA-402's GetOption is being removed in favor of a shared ECMA-262 GetOption in the Temporal proposal. -// Until Temporal is merged into ECMA-262, our implementation lives in the Temporal-specific AO file & namespace. -using Temporal::get_option; -using Temporal::OptionType; - } diff --git a/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp b/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp index 1465ee77ba3..36e49b69906 100644 --- a/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp +++ b/Libraries/LibJS/Runtime/Intl/DateTimeFormat.cpp @@ -485,7 +485,7 @@ bool same_temporal_type(FormattableDateTime const& x, FormattableDateTime const& static double to_epoch_milliseconds(Crypto::SignedBigInteger const& epoch_nanoseconds) { - return Temporal::big_floor(epoch_nanoseconds, Temporal::NANOSECONDS_PER_MILLISECOND).to_double(); + return big_floor(epoch_nanoseconds, Temporal::NANOSECONDS_PER_MILLISECOND).to_double(); } // 15.9.15 HandleDateTimeTemporalDate ( dateTimeFormat, temporalDate ), https://tc39.es/proposal-temporal/#sec-temporal-handledatetimetemporaldate diff --git a/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.cpp b/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.cpp index d9dc29c6068..3985d42fc6c 100644 --- a/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.cpp +++ b/Libraries/LibJS/Runtime/Intl/DisplayNamesConstructor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024, Tim Flynn + * Copyright (c) 2021-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -10,7 +10,6 @@ #include #include #include -#include #include namespace JS::Intl { @@ -64,7 +63,7 @@ ThrowCompletionOr> DisplayNamesConstructor::construct(FunctionOb return vm.throw_completion(ErrorType::IsUndefined, "options"sv); // 5. Set options to ? GetOptionsObject(options). - auto options = TRY(Temporal::get_options_object(vm, options_value)); + auto options = TRY(get_options_object(vm, options_value)); // 6. Let opt be a new Record. LocaleOptions opt {}; diff --git a/Libraries/LibJS/Runtime/Intl/DurationFormatConstructor.cpp b/Libraries/LibJS/Runtime/Intl/DurationFormatConstructor.cpp index 58fa42aeedb..eb1ead39bcd 100644 --- a/Libraries/LibJS/Runtime/Intl/DurationFormatConstructor.cpp +++ b/Libraries/LibJS/Runtime/Intl/DurationFormatConstructor.cpp @@ -60,7 +60,7 @@ ThrowCompletionOr> DurationFormatConstructor::construct(Function auto requested_locales = TRY(canonicalize_locale_list(vm, locales)); // 4. Let options be ? GetOptionsObject(options). - auto options = TRY(Temporal::get_options_object(vm, options_value)); + auto options = TRY(get_options_object(vm, options_value)); // 5. Let matcher be ? GetOption(options, "localeMatcher", STRING, « "lookup", "best fit" », "best fit"). auto matcher = TRY(get_option(vm, *options, vm.names.localeMatcher, OptionType::String, { "lookup"sv, "best fit"sv }, "best fit"sv)); diff --git a/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp b/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp index 1af09d66c4a..c33bb978be2 100644 --- a/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp +++ b/Libraries/LibJS/Runtime/Intl/ListFormatConstructor.cpp @@ -10,7 +10,6 @@ #include #include #include -#include namespace JS::Intl { @@ -59,7 +58,7 @@ ThrowCompletionOr> ListFormatConstructor::construct(FunctionObje auto requested_locales = TRY(canonicalize_locale_list(vm, locale_value)); // 4. Set options to ? GetOptionsObject(options). - auto options = TRY(Temporal::get_options_object(vm, options_value)); + auto options = TRY(get_options_object(vm, options_value)); // 5. Let opt be a new Record. LocaleOptions opt {}; diff --git a/Libraries/LibJS/Runtime/Intl/PluralRules.cpp b/Libraries/LibJS/Runtime/Intl/PluralRules.cpp index c45abd30668..935a6ee9667 100644 --- a/Libraries/LibJS/Runtime/Intl/PluralRules.cpp +++ b/Libraries/LibJS/Runtime/Intl/PluralRules.cpp @@ -5,6 +5,7 @@ */ #include +#include namespace JS::Intl { diff --git a/Libraries/LibJS/Runtime/Intl/SegmenterConstructor.cpp b/Libraries/LibJS/Runtime/Intl/SegmenterConstructor.cpp index 2d14e970808..a5279835ca4 100644 --- a/Libraries/LibJS/Runtime/Intl/SegmenterConstructor.cpp +++ b/Libraries/LibJS/Runtime/Intl/SegmenterConstructor.cpp @@ -11,7 +11,6 @@ #include #include #include -#include namespace JS::Intl { @@ -60,7 +59,7 @@ ThrowCompletionOr> SegmenterConstructor::construct(FunctionObjec auto requested_locales = TRY(canonicalize_locale_list(vm, locales)); // 5. Set options to ? GetOptionsObject(options). - auto options = TRY(Temporal::get_options_object(vm, options_value)); + auto options = TRY(get_options_object(vm, options_value)); // 6. Let opt be a new Record. LocaleOptions opt {}; diff --git a/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp b/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp index f147e45b86e..e9e282c09d6 100644 --- a/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp +++ b/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp @@ -2,13 +2,12 @@ * Copyright (c) 2021-2022, Idan Horowitz * Copyright (c) 2021-2023, Linus Groh * Copyright (c) 2021, Luke Wilde - * Copyright (c) 2024, Tim Flynn + * Copyright (c) 2024-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #include -#include #include #include #include @@ -1799,127 +1798,4 @@ ThrowCompletionOr get_difference_settings(VM& vm, DurationOp return DifferenceSettings { .smallest_unit = smallest_unit_value, .largest_unit = largest_unit_value, .rounding_mode = rounding_mode, .rounding_increment = rounding_increment }; } -// 14.4.1.1 GetOptionsObject ( options ), https://tc39.es/proposal-temporal/#sec-getoptionsobject -ThrowCompletionOr> get_options_object(VM& vm, Value options) -{ - auto& realm = *vm.current_realm(); - - // 1. If options is undefined, then - if (options.is_undefined()) { - // a. Return OrdinaryObjectCreate(null). - return Object::create(realm, nullptr); - } - - // 2. If options is an Object, then - if (options.is_object()) { - // a. Return options. - return options.as_object(); - } - - // 3. Throw a TypeError exception. - return vm.throw_completion(ErrorType::NotAnObject, "Options"); -} - -// 14.4.1.2 GetOption ( options, property, type, values, default ), https://tc39.es/proposal-temporal/#sec-getoption -ThrowCompletionOr get_option(VM& vm, Object const& options, PropertyKey const& property, OptionType type, ReadonlySpan values, OptionDefault const& default_) -{ - VERIFY(property.is_string()); - - // 1. Let value be ? Get(options, property). - auto value = TRY(options.get(property)); - - // 2. If value is undefined, then - if (value.is_undefined()) { - // a. If default is REQUIRED, throw a RangeError exception. - if (default_.has()) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, "undefined"sv, property.as_string()); - - // b. Return default. - return default_.visit( - [](Required) -> Value { VERIFY_NOT_REACHED(); }, - [](Empty) -> Value { return js_undefined(); }, - [](bool default_) -> Value { return Value { default_ }; }, - [](double default_) -> Value { return Value { default_ }; }, - [&](StringView default_) -> Value { return PrimitiveString::create(vm, default_); }); - } - - // 3. If type is BOOLEAN, then - if (type == OptionType::Boolean) { - // a. Set value to ToBoolean(value). - value = Value { value.to_boolean() }; - } - // 4. Else, - else { - // a. Assert: type is STRING. - VERIFY(type == OptionType::String); - - // b. Set value to ? ToString(value). - value = TRY(value.to_primitive_string(vm)); - } - - // 5. If values is not EMPTY and values does not contain value, throw a RangeError exception. - if (!values.is_empty()) { - // NOTE: Every location in the spec that invokes GetOption with type=boolean also has values=undefined. - VERIFY(value.is_string()); - - if (auto value_string = value.as_string().utf8_string(); !values.contains_slow(value_string)) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, value_string, property.as_string()); - } - - // 6. Return value. - return value; -} - -// 14.4.1.3 GetRoundingModeOption ( options, fallback ), https://tc39.es/proposal-temporal/#sec-temporal-getroundingmodeoption -ThrowCompletionOr get_rounding_mode_option(VM& vm, Object const& options, RoundingMode fallback) -{ - // 1. Let allowedStrings be the List of Strings from the "String Identifier" column of Table 26. - static constexpr auto allowed_strings = to_array({ "ceil"sv, "floor"sv, "expand"sv, "trunc"sv, "halfCeil"sv, "halfFloor"sv, "halfExpand"sv, "halfTrunc"sv, "halfEven"sv }); - - // 2. Let stringFallback be the value from the "String Identifier" column of the row with fallback in its "Rounding Mode" column. - auto string_fallback = allowed_strings[to_underlying(fallback)]; - - // 3. Let stringValue be ? GetOption(options, "roundingMode", STRING, allowedStrings, stringFallback). - auto string_value = TRY(get_option(vm, options, vm.names.roundingMode, OptionType::String, allowed_strings, string_fallback)); - - // 4. Return the value from the "Rounding Mode" column of the row with stringValue in its "String Identifier" column. - return static_cast(allowed_strings.first_index_of(string_value.as_string().utf8_string_view()).value()); -} - -// 14.4.1.4 GetRoundingIncrementOption ( options ), https://tc39.es/proposal-temporal/#sec-temporal-getroundingincrementoption -ThrowCompletionOr get_rounding_increment_option(VM& vm, Object const& options) -{ - // 1. Let value be ? Get(options, "roundingIncrement"). - auto value = TRY(options.get(vm.names.roundingIncrement)); - - // 2. If value is undefined, return 1𝔽. - if (value.is_undefined()) - return 1; - - // 3. Let integerIncrement be ? ToIntegerWithTruncation(value). - auto integer_increment = TRY(to_integer_with_truncation(vm, value, ErrorType::OptionIsNotValidValue, value, "roundingIncrement"sv)); - - // 4. If integerIncrement < 1 or integerIncrement > 10**9, throw a RangeError exception. - if (integer_increment < 1 || integer_increment > 1'000'000'000u) - return vm.throw_completion(ErrorType::OptionIsNotValidValue, value, "roundingIncrement"); - - // 5. Return integerIncrement. - return static_cast(integer_increment); -} - -// AD-HOC -// FIXME: We should add a generic floor() method to our BigInt classes. But for now, since we know we are only dividing -// by powers of 10, we can implement a very situationally specific method to compute the floor of a division. -Crypto::SignedBigInteger big_floor(Crypto::SignedBigInteger const& numerator, Crypto::UnsignedBigInteger const& denominator) -{ - auto result = numerator.divided_by(denominator); - - if (result.remainder.is_zero()) - return result.quotient; - if (!result.quotient.is_negative() && result.remainder.is_positive()) - return result.quotient; - - return result.quotient.minus(Crypto::SignedBigInteger { 1 }); -} - } diff --git a/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h b/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h index 04c800065cc..0979b606715 100644 --- a/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h +++ b/Libraries/LibJS/Runtime/Temporal/AbstractOperations.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2021, Idan Horowitz * Copyright (c) 2021-2023, Linus Groh - * Copyright (c) 2024, Tim Flynn + * Copyright (c) 2024-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -113,19 +114,6 @@ enum class UnitGroup { 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, @@ -142,7 +130,6 @@ enum class Sign { }; struct Auto { }; -struct Required { }; struct Unset { }; using Precision = Variant; using RoundingIncrement = Variant; @@ -271,31 +258,4 @@ ThrowCompletionOr to_integer_if_integral(VM& vm, Value argument, ErrorTy 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 week; - Optional year; -}; - -enum class OptionType { - Boolean, - String, -}; - -using OptionDefault = Variant; - -ThrowCompletionOr> get_options_object(VM&, Value options); -ThrowCompletionOr get_option(VM&, Object const& options, PropertyKey const& property, OptionType type, ReadonlySpan values, OptionDefault const&); - -template -ThrowCompletionOr 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 { values }, default_); -} - -ThrowCompletionOr get_rounding_mode_option(VM&, Object const& options, RoundingMode fallback); -ThrowCompletionOr get_rounding_increment_option(VM&, Object const& options); - -Crypto::SignedBigInteger big_floor(Crypto::SignedBigInteger const& numerator, Crypto::UnsignedBigInteger const& denominator); - } diff --git a/Libraries/LibJS/Runtime/Uint8Array.cpp b/Libraries/LibJS/Runtime/Uint8Array.cpp index 89dffdcd322..6ab8ad84e69 100644 --- a/Libraries/LibJS/Runtime/Uint8Array.cpp +++ b/Libraries/LibJS/Runtime/Uint8Array.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Tim Flynn + * Copyright (c) 2024-2025, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -87,7 +87,7 @@ JS_DEFINE_NATIVE_FUNCTION(Uint8ArrayPrototypeHelpers::to_base64) auto typed_array = TRY(validate_uint8_array(vm)); // 3. Let opts be ? GetOptionsObject(options). - auto options = TRY(Temporal::get_options_object(vm, options_value)); + auto options = TRY(get_options_object(vm, options_value)); // 4. Let alphabet be ? Get(opts, "alphabet"). // 5. If alphabet is undefined, set alphabet to "base64". @@ -159,7 +159,7 @@ JS_DEFINE_NATIVE_FUNCTION(Uint8ArrayConstructorHelpers::from_base64) return vm.throw_completion(ErrorType::NotAString, string_value); // 2. Let opts be ? GetOptionsObject(options). - auto options = TRY(Temporal::get_options_object(vm, options_value)); + auto options = TRY(get_options_object(vm, options_value)); // 3. Let alphabet be ? Get(opts, "alphabet"). // 4. If alphabet is undefined, set alphabet to "base64". @@ -214,7 +214,7 @@ JS_DEFINE_NATIVE_FUNCTION(Uint8ArrayPrototypeHelpers::set_from_base64) return vm.throw_completion(ErrorType::NotAString, string_value); // 4. Let opts be ? GetOptionsObject(options). - auto options = TRY(Temporal::get_options_object(vm, options_value)); + auto options = TRY(get_options_object(vm, options_value)); // 5. Let alphabet be ? Get(opts, "alphabet"). // 6. If alphabet is undefined, set alphabet to "base64".