LibJS: Standardize the spec-order of Intl.DurationFormat definitions

This is an editorial change in the ECMA-402 spec. See:
54ca35d
6cdcab3
e4cbfba
This commit is contained in:
Timothy Flynn 2025-03-03 08:22:16 -05:00 committed by Tim Flynn
commit 56a6daee4d
Notes: github-actions[bot] 2025-03-04 12:37:25 +00:00
5 changed files with 97 additions and 97 deletions

View file

@ -185,7 +185,7 @@ static GC::Ref<ListFormat> construct_list_format(VM& vm, DurationFormat const& d
return static_cast<ListFormat&>(*list_format);
}
// 13.1.6 GetDurationUnitOptions ( unit, options, baseStyle, stylesList, digitalBase, prevStyle, twoDigitHours ), https://tc39.es/ecma402/#sec-getdurationunitoptions
// 13.5.6 GetDurationUnitOptions ( unit, options, baseStyle, stylesList, digitalBase, prevStyle, twoDigitHours ), https://tc39.es/ecma402/#sec-getdurationunitoptions
ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(VM& vm, DurationFormat::Unit unit, Object const& options, DurationFormat::Style base_style, ReadonlySpan<StringView> styles_list, DurationFormat::ValueStyle digital_base, Optional<DurationFormat::ValueStyle> previous_style, bool two_digit_hours)
{
auto const& unit_property_key = unit_to_property_key(vm, unit);
@ -295,7 +295,7 @@ ThrowCompletionOr<DurationUnitOptions> get_duration_unit_options(VM& vm, Duratio
return DurationUnitOptions { .style = style, .display = display };
}
// 13.1.7 ComputeFractionalDigits ( durationFormat, duration ), https://tc39.es/ecma402/#sec-computefractionaldigits
// 13.5.7 ComputeFractionalDigits ( durationFormat, duration ), https://tc39.es/ecma402/#sec-computefractionaldigits
// 15.9.6 ComputeFractionalDigits ( durationFormat, duration ), https://tc39.es/proposal-temporal/#sec-computefractionaldigits
Crypto::BigFraction compute_fractional_digits(DurationFormat const& duration_format, Temporal::Duration const& duration)
{
@ -305,7 +305,7 @@ Crypto::BigFraction compute_fractional_digits(DurationFormat const& duration_for
// 2. Let exponent be 3.
double exponent = 3;
// 3. For each row of Table 21, except the header row, in table order, do
// 3. For each row of Table 23, except the header row, in table order, do
for (auto const& duration_instances_component : duration_instances_components) {
// a. Let style be the value of durationFormat's internal slot whose name is the Style Slot value of the current row.
auto style = (duration_format.*duration_instances_component.get_style_slot)();
@ -334,7 +334,7 @@ Crypto::BigFraction compute_fractional_digits(DurationFormat const& duration_for
return result;
}
// 13.1.8 NextUnitFractional ( durationFormat, unit ), https://tc39.es/ecma402/#sec-nextunitfractional
// 13.5.8 NextUnitFractional ( durationFormat, unit ), https://tc39.es/ecma402/#sec-nextunitfractional
bool next_unit_fractional(DurationFormat const& duration_format, DurationFormat::Unit unit)
{
// 1. Assert: unit is "seconds", "milliseconds", or "microseconds".
@ -356,7 +356,7 @@ bool next_unit_fractional(DurationFormat const& duration_format, DurationFormat:
return false;
}
// 13.1.9 FormatNumericHours ( durationFormat, hoursValue, signDisplayed ), https://tc39.es/ecma402/#sec-formatnumerichours
// 13.5.9 FormatNumericHours ( durationFormat, hoursValue, signDisplayed ), https://tc39.es/ecma402/#sec-formatnumerichours
Vector<DurationFormatPart> format_numeric_hours(VM& vm, DurationFormat const& duration_format, MathematicalValue const& hours_value, bool sign_displayed)
{
auto& realm = *vm.current_realm();
@ -412,7 +412,7 @@ Vector<DurationFormatPart> format_numeric_hours(VM& vm, DurationFormat const& du
return result;
}
// 13.1.10 FormatNumericMinutes ( durationFormat, minutesValue, hoursDisplayed, signDisplayed ), https://tc39.es/ecma402/#sec-formatnumericminutes
// 13.5.10 FormatNumericMinutes ( durationFormat, minutesValue, hoursDisplayed, signDisplayed ), https://tc39.es/ecma402/#sec-formatnumericminutes
Vector<DurationFormatPart> format_numeric_minutes(VM& vm, DurationFormat const& duration_format, MathematicalValue const& minutes_value, bool hours_displayed, bool sign_displayed)
{
auto& realm = *vm.current_realm();
@ -477,7 +477,7 @@ Vector<DurationFormatPart> format_numeric_minutes(VM& vm, DurationFormat const&
return result;
}
// 13.1.11 FormatNumericSeconds ( durationFormat, secondsValue, minutesDisplayed, signDisplayed ), https://tc39.es/ecma402/#sec-formatnumericseconds
// 13.5.11 FormatNumericSeconds ( durationFormat, secondsValue, minutesDisplayed, signDisplayed ), https://tc39.es/ecma402/#sec-formatnumericseconds
Vector<DurationFormatPart> format_numeric_seconds(VM& vm, DurationFormat const& duration_format, MathematicalValue const& seconds_value, bool minutes_displayed, bool sign_displayed)
{
auto& realm = *vm.current_realm();
@ -571,7 +571,7 @@ Vector<DurationFormatPart> format_numeric_seconds(VM& vm, DurationFormat const&
return result;
}
// 13.1.12 FormatNumericUnits ( durationFormat, duration, firstNumericUnit, signDisplayed ), https://tc39.es/ecma402/#sec-formatnumericunits
// 13.5.12 FormatNumericUnits ( durationFormat, duration, firstNumericUnit, signDisplayed ), https://tc39.es/ecma402/#sec-formatnumericunits
// 15.9.7 FormatNumericUnits ( durationFormat, duration, firstNumericUnit, signDisplayed ), https://tc39.es/proposal-temporal/#sec-formatnumericunits
Vector<DurationFormatPart> format_numeric_units(VM& vm, DurationFormat const& duration_format, Temporal::Duration const& duration, DurationFormat::Unit first_numeric_unit, bool sign_displayed)
{
@ -699,7 +699,7 @@ Vector<DurationFormatPart> format_numeric_units(VM& vm, DurationFormat const& du
return numeric_parts_list;
}
// 13.1.13 ListFormatParts ( durationFormat, partitionedPartsList ), https://tc39.es/ecma402/#sec-listformatparts
// 13.5.13 ListFormatParts ( durationFormat, partitionedPartsList ), https://tc39.es/ecma402/#sec-listformatparts
Vector<DurationFormatPart> list_format_parts(VM& vm, DurationFormat const& duration_format, Vector<Vector<DurationFormatPart>>& partitioned_parts_list)
{
auto& realm = *vm.current_realm();
@ -790,7 +790,7 @@ Vector<DurationFormatPart> list_format_parts(VM& vm, DurationFormat const& durat
return flattened_parts_list;
}
// 13.1.14 PartitionDurationFormatPattern ( durationFormat, duration ), https://tc39.es/ecma402/#sec-partitiondurationformatpattern
// 13.5.14 PartitionDurationFormatPattern ( durationFormat, duration ), https://tc39.es/ecma402/#sec-partitiondurationformatpattern
// 15.9.8 PartitionDurationFormatPattern ( durationFormat, duration ), https://tc39.es/proposal-temporal/#sec-formatnumericunits
Vector<DurationFormatPart> partition_duration_format_pattern(VM& vm, DurationFormat const& duration_format, Temporal::Duration const& duration)
{
@ -805,7 +805,7 @@ Vector<DurationFormatPart> partition_duration_format_pattern(VM& vm, DurationFor
// 3. Let numericUnitFound be false.
auto numeric_unit_found = false;
// 4. While numericUnitFound is false, repeat for each row in Table 21 in table order, except the header row:
// 4. While numericUnitFound is false, repeat for each row in Table 23 in table order, except the header row:
for (size_t i = 0; !numeric_unit_found && i < duration_instances_components.size(); ++i) {
auto const& duration_instances_component = duration_instances_components[i];

View file

@ -68,7 +68,7 @@ public:
static constexpr auto relevant_extension_keys()
{
// 13.3.3 Internal slots, https://tc39.es/ecma402/#sec-Intl.DurationFormat-internal-slots
// 13.2.3 Internal slots, https://tc39.es/ecma402/#sec-Intl.DurationFormat-internal-slots
// The value of the [[RelevantExtensionKeys]] internal slot is « "nu" ».
return AK::Array { "nu"sv };
}
@ -218,8 +218,8 @@ struct DurationInstanceComponent {
DurationFormat::ValueStyle digital_default;
};
// Table 21: DurationFormat instance internal slots and properties relevant to PartitionDurationFormatPattern, https://tc39.es/ecma402/#table-partition-duration-format-pattern
// Table 22: Internal slots and property names of DurationFormat instances relevant to Intl.DurationFormat constructor, https://tc39.es/ecma402/#table-durationformat
// Table 20: Internal slots and property names of DurationFormat instances relevant to Intl.DurationFormat constructor, https://tc39.es/ecma402/#table-durationformat
// Table 23: DurationFormat instance internal slots and properties relevant to PartitionDurationFormatPattern, https://tc39.es/ecma402/#table-partition-duration-format-pattern
static constexpr auto date_values = AK::Array { "long"sv, "short"sv, "narrow"sv };
static constexpr auto time_values = AK::Array { "long"sv, "short"sv, "narrow"sv, "numeric"sv, "2-digit"sv };
static constexpr auto sub_second_values = AK::Array { "long"sv, "short"sv, "narrow"sv, "numeric"sv };

View file

@ -18,7 +18,7 @@ namespace JS::Intl {
GC_DEFINE_ALLOCATOR(DurationFormatConstructor);
// 13.2 The Intl.DurationFormat Constructor, https://tc39.es/ecma402/#sec-intl-durationformat-constructor
// 13.1 The Intl.DurationFormat Constructor, https://tc39.es/ecma402/#sec-intl-durationformat-constructor
DurationFormatConstructor::DurationFormatConstructor(Realm& realm)
: NativeFunction(realm.vm().names.DurationFormat.as_string(), realm.intrinsics().function_prototype())
{
@ -38,14 +38,14 @@ void DurationFormatConstructor::initialize(Realm& realm)
define_native_function(realm, vm.names.supportedLocalesOf, supported_locales_of, 1, attr);
}
// 13.2.1 Intl.DurationFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-Intl.DurationFormat
// 13.1.1 Intl.DurationFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-Intl.DurationFormat
ThrowCompletionOr<Value> DurationFormatConstructor::call()
{
// 1. If NewTarget is undefined, throw a TypeError exception.
return vm().throw_completion<TypeError>(ErrorType::ConstructorWithoutNew, "Intl.DurationFormat");
}
// 13.2.1 Intl.DurationFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-Intl.DurationFormat
// 13.1.1 Intl.DurationFormat ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sec-Intl.DurationFormat
ThrowCompletionOr<GC::Ref<Object>> DurationFormatConstructor::construct(FunctionObject& new_target)
{
auto& vm = this->vm();
@ -110,7 +110,7 @@ ThrowCompletionOr<GC::Ref<Object>> DurationFormatConstructor::construct(Function
// 18. Let prevStyle be the empty String.
Optional<DurationFormat::ValueStyle> previous_style;
// 19. For each row of Table 22, except the header row, in table order, do
// 19. For each row of Table 20, except the header row, in table order, do
for (auto const& duration_instances_component : duration_instances_components) {
// a. Let styleSlot be the Style Slot value of the current row.
auto style_slot = duration_instances_component.set_style_slot;
@ -150,7 +150,7 @@ ThrowCompletionOr<GC::Ref<Object>> DurationFormatConstructor::construct(Function
return duration_format;
}
// 13.3.2 Intl.DurationFormat.supportedLocalesOf ( locales [ , options ] ), https://tc39.es/ecma402/#sec-Intl.DurationFormat.supportedLocalesOf
// 13.2.2 Intl.DurationFormat.supportedLocalesOf ( locales [ , options ] ), https://tc39.es/ecma402/#sec-Intl.DurationFormat.supportedLocalesOf
JS_DEFINE_NATIVE_FUNCTION(DurationFormatConstructor::supported_locales_of)
{
auto locales = vm.argument(0);

View file

@ -16,7 +16,7 @@ namespace JS::Intl {
GC_DEFINE_ALLOCATOR(DurationFormatPrototype);
// 13.4 Properties of the Intl.DurationFormat Prototype Object, https://tc39.es/ecma402/#sec-properties-of-intl-durationformat-prototype-object
// 13.3 Properties of the Intl.DurationFormat Prototype Object, https://tc39.es/ecma402/#sec-properties-of-intl-durationformat-prototype-object
DurationFormatPrototype::DurationFormatPrototype(Realm& realm)
: PrototypeObject(realm.intrinsics().object_prototype())
{
@ -28,88 +28,16 @@ void DurationFormatPrototype::initialize(Realm& realm)
auto& vm = this->vm();
// 13.4.2 Intl.DurationFormat.prototype [ @@toStringTag ], https://tc39.es/ecma402/#sec-Intl.DurationFormat.prototype-@@tostringtag
// 13.3.5 Intl.DurationFormat.prototype [ %Symbol.toStringTag% ], https://tc39.es/ecma402/#sec-Intl.DurationFormat.prototype-%symbol.tostringtag%
define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, "Intl.DurationFormat"_string), Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function(realm, vm.names.resolvedOptions, resolved_options, 0, attr);
define_native_function(realm, vm.names.format, format, 1, attr);
define_native_function(realm, vm.names.formatToParts, format_to_parts, 1, attr);
define_native_function(realm, vm.names.resolvedOptions, resolved_options, 0, attr);
}
// 13.4.3 Intl.DurationFormat.prototype.format ( duration ), https://tc39.es/ecma402/#sec-Intl.DurationFormat.prototype.format
// 15.10.1 Intl.DurationFormat.prototype.format ( durationLike ), https://tc39.es/proposal-temporal/#sec-Intl.DurationFormat.prototype.format
JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::format)
{
// 1. Let df be this value.
// 2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
auto duration_format = TRY(typed_this_object(vm));
// 3. Let duration be ? ToTemporalDuration(durationLike).
auto duration = TRY(Temporal::to_temporal_duration(vm, vm.argument(0)));
// 4. Let parts be PartitionDurationFormatPattern(df, duration).
auto parts = partition_duration_format_pattern(vm, duration_format, duration);
// 5. Let result be a new empty String.
StringBuilder result;
// 6. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
for (auto const& part : parts) {
// a. Set result to the string-concatenation of result and part.[[Value]].
result.append(part.value);
}
// 7. Return result.
return PrimitiveString::create(vm, MUST(result.to_string()));
}
// 13.4.4 Intl.DurationFormat.prototype.formatToParts ( duration ), https://tc39.es/ecma402/#sec-Intl.DurationFormat.prototype.formatToParts
// 15.10.2 Intl.DurationFormat.prototype.formatToParts ( durationLike ), https://tc39.es/proposal-temporal/#sec-Intl.DurationFormat.prototype.formatToParts
JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::format_to_parts)
{
auto& realm = *vm.current_realm();
// 1. Let df be this value.
// 2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
auto duration_format = TRY(typed_this_object(vm));
// 3. Let duration be ? ToTemporalDuration(durationLike).
auto duration = TRY(Temporal::to_temporal_duration(vm, vm.argument(0)));
// 4. Let parts be PartitionDurationFormatPattern(df, duration).
auto parts = partition_duration_format_pattern(vm, duration_format, duration);
// 5. Let result be ! ArrayCreate(0).
auto result = MUST(Array::create(realm, 0));
// 6. Let n be 0.
// 7. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
for (auto [n, part] : enumerate(parts)) {
// a. Let obj be OrdinaryObjectCreate(%Object.prototype%).
auto object = Object::create(realm, realm.intrinsics().object_prototype());
// b. Perform ! CreateDataPropertyOrThrow(obj, "type", part.[[Type]]).
MUST(object->create_data_property_or_throw(vm.names.type, PrimitiveString::create(vm, part.type)));
// c. Perform ! CreateDataPropertyOrThrow(obj, "value", part.[[Value]]).
MUST(object->create_data_property_or_throw(vm.names.value, PrimitiveString::create(vm, move(part.value))));
// d. If part.[[Unit]] is not empty, perform ! CreateDataPropertyOrThrow(obj, "unit", part.[[Unit]]).
if (!part.unit.is_empty())
MUST(object->create_data_property_or_throw(vm.names.unit, PrimitiveString::create(vm, part.unit)));
// e. Perform ! CreateDataPropertyOrThrow(result, ! ToString(n), obj).
MUST(result->create_data_property_or_throw(n, object));
// f. Set n to n + 1.
}
// 8. Return result.
return result;
}
// 13.4.5 Intl.DurationFormat.prototype.resolvedOptions ( ), https://tc39.es/ecma402/#sec-Intl.DurationFormat.prototype.resolvedOptions
// 13.3.2 Intl.DurationFormat.prototype.resolvedOptions ( ), https://tc39.es/ecma402/#sec-Intl.DurationFormat.prototype.resolvedOptions
JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::resolved_options)
{
auto& realm = *vm.current_realm();
@ -121,7 +49,7 @@ JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::resolved_options)
// 3. Let options be OrdinaryObjectCreate(%Object.prototype%).
auto options = Object::create(realm, realm.intrinsics().object_prototype());
// 4. For each row of Table 23, except the header row, in table order, do
// 4. For each row of Table 21, except the header row, in table order, do
auto create_option = [&](PropertyKey const& property, StringView value) {
// a. Let p be the Property value of the current row.
// b. Let v be the value of df's internal slot whose name is the Internal Slot value of the current row.
@ -174,4 +102,76 @@ JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::resolved_options)
return options;
}
// 13.3.3 Intl.DurationFormat.prototype.format ( duration ), https://tc39.es/ecma402/#sec-Intl.DurationFormat.prototype.format
// 15.10.1 Intl.DurationFormat.prototype.format ( durationLike ), https://tc39.es/proposal-temporal/#sec-Intl.DurationFormat.prototype.format
JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::format)
{
// 1. Let df be this value.
// 2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
auto duration_format = TRY(typed_this_object(vm));
// 3. Let duration be ? ToTemporalDuration(durationLike).
auto duration = TRY(Temporal::to_temporal_duration(vm, vm.argument(0)));
// 4. Let parts be PartitionDurationFormatPattern(df, duration).
auto parts = partition_duration_format_pattern(vm, duration_format, duration);
// 5. Let result be a new empty String.
StringBuilder result;
// 6. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
for (auto const& part : parts) {
// a. Set result to the string-concatenation of result and part.[[Value]].
result.append(part.value);
}
// 7. Return result.
return PrimitiveString::create(vm, MUST(result.to_string()));
}
// 13.3.4 Intl.DurationFormat.prototype.formatToParts ( duration ), https://tc39.es/ecma402/#sec-Intl.DurationFormat.prototype.formatToParts
// 15.10.2 Intl.DurationFormat.prototype.formatToParts ( durationLike ), https://tc39.es/proposal-temporal/#sec-Intl.DurationFormat.prototype.formatToParts
JS_DEFINE_NATIVE_FUNCTION(DurationFormatPrototype::format_to_parts)
{
auto& realm = *vm.current_realm();
// 1. Let df be this value.
// 2. Perform ? RequireInternalSlot(df, [[InitializedDurationFormat]]).
auto duration_format = TRY(typed_this_object(vm));
// 3. Let duration be ? ToTemporalDuration(durationLike).
auto duration = TRY(Temporal::to_temporal_duration(vm, vm.argument(0)));
// 4. Let parts be PartitionDurationFormatPattern(df, duration).
auto parts = partition_duration_format_pattern(vm, duration_format, duration);
// 5. Let result be ! ArrayCreate(0).
auto result = MUST(Array::create(realm, 0));
// 6. Let n be 0.
// 7. For each Record { [[Type]], [[Value]], [[Unit]] } part in parts, do
for (auto [n, part] : enumerate(parts)) {
// a. Let obj be OrdinaryObjectCreate(%Object.prototype%).
auto object = Object::create(realm, realm.intrinsics().object_prototype());
// b. Perform ! CreateDataPropertyOrThrow(obj, "type", part.[[Type]]).
MUST(object->create_data_property_or_throw(vm.names.type, PrimitiveString::create(vm, part.type)));
// c. Perform ! CreateDataPropertyOrThrow(obj, "value", part.[[Value]]).
MUST(object->create_data_property_or_throw(vm.names.value, PrimitiveString::create(vm, move(part.value))));
// d. If part.[[Unit]] is not empty, perform ! CreateDataPropertyOrThrow(obj, "unit", part.[[Unit]]).
if (!part.unit.is_empty())
MUST(object->create_data_property_or_throw(vm.names.unit, PrimitiveString::create(vm, part.unit)));
// e. Perform ! CreateDataPropertyOrThrow(result, ! ToString(n), obj).
MUST(result->create_data_property_or_throw(n, object));
// f. Set n to n + 1.
}
// 8. Return result.
return result;
}
}

View file

@ -22,9 +22,9 @@ public:
private:
explicit DurationFormatPrototype(Realm&);
JS_DECLARE_NATIVE_FUNCTION(resolved_options);
JS_DECLARE_NATIVE_FUNCTION(format);
JS_DECLARE_NATIVE_FUNCTION(format_to_parts);
JS_DECLARE_NATIVE_FUNCTION(resolved_options);
};
}