diff --git a/src/builtins/builtins-temporal.cc b/src/builtins/builtins-temporal.cc index 5d56668dea..ad2f239bf2 100644 --- a/src/builtins/builtins-temporal.cc +++ b/src/builtins/builtins-temporal.cc @@ -58,10 +58,6 @@ TO_BE_IMPLEMENTED(TemporalPlainTimePrototypeUntil) TO_BE_IMPLEMENTED(TemporalPlainTimePrototypeSince) /* Temporal #sec-temporal.plaintime.prototype.round */ TO_BE_IMPLEMENTED(TemporalPlainTimePrototypeRound) -/* Temporal #sec-temporal.plaintime.prototype.tolocalestring */ -TO_BE_IMPLEMENTED(TemporalPlainTimePrototypeToLocaleString) -/* Temporal #sec-temporal.plaintime.prototype.tostring */ -TO_BE_IMPLEMENTED(TemporalPlainTimePrototypeToString) /* Temporal.PlaneDateTime */ /* Temporal #sec-temporal.plaindatetime.prototype.add */ @@ -408,6 +404,8 @@ TEMPORAL_PROTOTYPE_METHOD1(PlainTime, ToPlainDateTime, toPlainDateTime) TEMPORAL_PROTOTYPE_METHOD2(PlainTime, With, with) TEMPORAL_VALUE_OF(PlainTime) TEMPORAL_PROTOTYPE_METHOD0(PlainTime, ToJSON, toJSON) +TEMPORAL_PROTOTYPE_METHOD2(PlainTime, ToLocaleString, toLocaleString) +TEMPORAL_PROTOTYPE_METHOD1(PlainTime, ToString, toString) // PlainDateTime BUILTIN(TemporalPlainDateTimeConstructor) { diff --git a/src/init/heap-symbols.h b/src/init/heap-symbols.h index 93ccb8c4fe..2e50c83fb6 100644 --- a/src/init/heap-symbols.h +++ b/src/init/heap-symbols.h @@ -43,7 +43,6 @@ V(_, format_string, "format") \ V(_, fraction_string, "fraction") \ V(_, fractionalSecond_string, "fractionalSecond") \ - V(_, fractionalSecondDigits_string, "fractionalSecondDigits") \ V(_, full_string, "full") \ V(_, granularity_string, "granularity") \ V(_, grapheme_string, "grapheme") \ @@ -239,6 +238,7 @@ V(_, flags_string, "flags") \ V(_, Float32Array_string, "Float32Array") \ V(_, Float64Array_string, "Float64Array") \ + V(_, fractionalSecondDigits_string, "fractionalSecondDigits") \ V(_, from_string, "from") \ V(_, Function_string, "Function") \ V(_, function_native_code_string, "function () { [native code] }") \ diff --git a/src/objects/js-temporal-objects.cc b/src/objects/js-temporal-objects.cc index d78494689a..ba4696fc91 100644 --- a/src/objects/js-temporal-objects.cc +++ b/src/objects/js-temporal-objects.cc @@ -169,6 +169,9 @@ enum class ShowCalendar { kAuto, kAlways, kNever }; enum class Precision { k0, k1, k2, k3, k4, k5, k6, k7, k8, k9, kAuto, kMinute }; +// sec-temporal-totemporalroundingmode +enum class RoundingMode { kCeil, kFloor, kTrunc, kHalfExpand }; + // ISO8601 String Parsing // #sec-temporal-parsetemporalcalendarstring @@ -1404,27 +1407,36 @@ void FormatSecondsStringPart(IncrementalStringBuilder* builder, int32_t second, // #sec-temporal-temporaltimetostring Handle TemporalTimeToString(Isolate* isolate, - Handle temporal_time, + const TimeRecordCommon& time, Precision precision) { // 1. Assert: hour, minute, second, millisecond, microsecond and nanosecond // are integers. IncrementalStringBuilder builder(isolate); // 2. Let hour be ToZeroPaddedDecimalString(hour, 2). - ToZeroPaddedDecimalString(&builder, temporal_time->iso_hour(), 2); + ToZeroPaddedDecimalString(&builder, time.hour, 2); builder.AppendCharacter('-'); // 3. Let minute be ToZeroPaddedDecimalString(minute, 2). - ToZeroPaddedDecimalString(&builder, temporal_time->iso_minute(), 2); + ToZeroPaddedDecimalString(&builder, time.minute, 2); // 4. Let seconds be ! FormatSecondsStringPart(second, millisecond, // microsecond, nanosecond, precision). - FormatSecondsStringPart(&builder, temporal_time->iso_second(), - temporal_time->iso_millisecond(), - temporal_time->iso_microsecond(), - temporal_time->iso_nanosecond(), precision); + FormatSecondsStringPart(&builder, time.second, time.millisecond, + time.microsecond, time.nanosecond, precision); // 5. Return the string-concatenation of hour, the code unit 0x003A (COLON), // minute, and seconds. return builder.Finish().ToHandleChecked(); } +Handle TemporalTimeToString(Isolate* isolate, + Handle temporal_time, + Precision precision) { + return TemporalTimeToString( + isolate, + {temporal_time->iso_hour(), temporal_time->iso_minute(), + temporal_time->iso_second(), temporal_time->iso_millisecond(), + temporal_time->iso_microsecond(), temporal_time->iso_nanosecond()}, + precision); +} + } // namespace namespace temporal { @@ -1973,6 +1985,19 @@ Maybe ToTemporalOverflowForSideEffects(Isolate* isolate, return Just(true); } +// sec-temporal-totemporalroundingmode +Maybe ToTemporalRoundingMode(Isolate* isolate, + Handle options, + RoundingMode fallback, + const char* method_name) { + return GetStringOption( + isolate, options, "roundingMode", method_name, + {"ceil", "floor", "trunc", "halfExpand"}, + {RoundingMode::kCeil, RoundingMode::kFloor, RoundingMode::kTrunc, + RoundingMode::kHalfExpand}, + fallback); +} + // #sec-temporal-totemporaldisambiguation Maybe ToTemporalDisambiguation(Isolate* isolate, Handle options, @@ -4358,6 +4383,54 @@ Maybe ToTemporalTimeRecord( method_name); } +// #sec-temporal-tolargesttemporalunit +Maybe ToSmallestTemporalUnit(Isolate* isolate, + Handle normalized_options, + const std::set& disallowed_units, + Unit fallback, const char* method_name) { + // 1. Assert: disallowedUnits does not contain fallback. + DCHECK_EQ(disallowed_units.find(fallback), disallowed_units.end()); + // 2. Let smallestUnit be ? GetOption(normalizedOptions, "smallestUnit", « + // String », « "year", "years", "month", "months", "week", "weeks", "day", + // "days", "hour", "hours", "minute", "minutes", "second", "seconds", + // "millisecond", "milliseconds", "microsecond", "microseconds", "nanosecond", + // "nanoseconds" », fallback). + Unit smallest_unit; + MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE( + isolate, smallest_unit, + GetStringOption( + isolate, normalized_options, "smallestUnit", method_name, + {"year", "years", "month", "months", + "week", "weeks", "day", "days", + "hour", "hours", "minute", "minutes", + "second", "seconds", "millisecond", "milliseconds", + "microsecond", "microseconds", "nanosecond", "nanoseconds"}, + {Unit::kYear, Unit::kYear, Unit::kMonth, + Unit::kMonth, Unit::kWeek, Unit::kWeek, + Unit::kDay, Unit::kDay, Unit::kHour, + Unit::kHour, Unit::kMinute, Unit::kMinute, + Unit::kSecond, Unit::kSecond, Unit::kMillisecond, + Unit::kMillisecond, Unit::kMicrosecond, Unit::kMicrosecond, + Unit::kNanosecond, Unit::kNanosecond}, + fallback), + Nothing()); + // 3. If smallestUnit is in the Plural column of Table 12, then + // a. Set smallestUnit to the corresponding Singular value of the same row. + // 4. If disallowedUnits contains smallestUnit, then + if (disallowed_units.find(smallest_unit) != disallowed_units.end()) { + // a. Throw a RangeError exception. + THROW_NEW_ERROR_RETURN_VALUE( + isolate, + NewRangeError( + MessageTemplate::kInvalidUnit, + isolate->factory()->NewStringFromAsciiChecked(method_name), + isolate->factory()->smallestUnit_string()), + Nothing()); + } + // 5. Return smallestUnit. + return Just(smallest_unit); +} + // #sec-temporal-mergelargestunitoption MaybeHandle MergeLargestUnitOption(Isolate* isolate, Handle options_obj, @@ -10359,6 +10432,415 @@ MaybeHandle JSTemporalPlainTime::ToJSON( return TemporalTimeToString(isolate, temporal_time, Precision::kAuto); } +// #sup-temporal.plaintime.prototype.tolocalestring +MaybeHandle JSTemporalPlainTime::ToLocaleString( + Isolate* isolate, Handle temporal_time, + Handle locales, Handle options) { + // TODO(ftang) Implement #sup-temporal.plaintime.prototype.tolocalestring + return TemporalTimeToString(isolate, temporal_time, Precision::kAuto); +} + +namespace { + +double RoundNumberToIncrement(Isolate* isolate, double x, double increment, + RoundingMode rounding_mode) { + TEMPORAL_ENTER_FUNC(); + + // 3. Let quotient be x / increment. + double rounded; + switch (rounding_mode) { + // 4. If roundingMode is "ceil", then + case RoundingMode::kCeil: + // a. Let rounded be −floor(−quotient). + rounded = -std::floor(-x / increment); + break; + // 5. Else if roundingMode is "floor", then + case RoundingMode::kFloor: + // a. Let rounded be floor(quotient). + rounded = std::floor(x / increment); + break; + // 6. Else if roundingMode is "trunc", then + case RoundingMode::kTrunc: + // a. Let rounded be the integral part of quotient, removing any + // fractional digits. + rounded = + (x > 0) ? std::floor(x / increment) : -std::floor(-x / increment); + break; + // 7. Else, + default: + // a. Let rounded be ! RoundHalfAwayFromZero(quotient). + rounded = std::round(x / increment); + break; + } + // 8. Return rounded × increment. + return rounded * increment; +} + +DateTimeRecordCommon RoundTime(Isolate* isolate, const TimeRecordCommon& time, + double increment, Unit unit, + RoundingMode rounding_mode, + double day_length_ns) { + TEMPORAL_ENTER_FUNC(); + + // 1. Assert: hour, minute, second, millisecond, microsecond, nanosecond, and + // increment are integers. + // 2. Let fractionalSecond be nanosecond × 10^−9 + microsecond × 10^−6 + + // millisecond × 10−3 + second. + double fractional_second = + static_cast(time.nanosecond) / 100000000.0 + + static_cast(time.microsecond) / 1000000.0 + + static_cast(time.millisecond) / 1000.0 + + static_cast(time.second); + double quantity; + switch (unit) { + // 3. If unit is "day", then + case Unit::kDay: + // a. If dayLengthNs is not present, set it to 8.64 × 10^13. + // b. Let quantity be (((((hour × 60 + minute) × 60 + second) × 1000 + + // millisecond) × 1000 + microsecond) × 1000 + nanosecond) / dayLengthNs. + quantity = + (((((time.hour * 60.0 + time.minute) * 60.0 + time.second) * 1000.0 + + time.millisecond) * + 1000.0 + + time.microsecond) * + 1000.0 + + time.nanosecond) / + day_length_ns; + break; + // 4. Else if unit is "hour", then + case Unit::kHour: + // a. Let quantity be (fractionalSecond / 60 + minute) / 60 + hour. + quantity = (fractional_second / 60.0 + time.minute) / 60.0 + time.hour; + break; + // 5. Else if unit is "minute", then + case Unit::kMinute: + // a. Let quantity be fractionalSecond / 60 + minute. + quantity = fractional_second / 60.0 + time.minute; + break; + // 6. Else if unit is "second", then + case Unit::kSecond: + // a. Let quantity be fractionalSecond. + quantity = fractional_second; + break; + // 7. Else if unit is "millisecond", then + case Unit::kMillisecond: + // a. Let quantity be nanosecond × 10^−6 + microsecond × 10^−3 + + // millisecond. + quantity = time.nanosecond / 1000000.0 + time.microsecond / 1000.0 + + time.millisecond; + break; + // 8. Else if unit is "microsecond", then + case Unit::kMicrosecond: + // a. Let quantity be nanosecond × 10^−3 + microsecond. + quantity = time.nanosecond / 1000.0 + time.microsecond; + break; + // 9. Else, + default: + // a. Assert: unit is "nanosecond". + DCHECK_EQ(unit, Unit::kNanosecond); + // b. Let quantity be nanosecond. + quantity = time.nanosecond; + break; + } + // 10. Let result be ! RoundNumberToIncrement(quantity, increment, + // roundingMode). + int32_t result = + RoundNumberToIncrement(isolate, quantity, increment, rounding_mode); + + switch (unit) { + // 11. If unit is "day", then + case Unit::kDay: + // a. Return the Record { [[Days]]: result, [[Hour]]: 0, [[Minute]]: 0, + // [[Second]]: 0, [[Millisecond]]: 0, [[Microsecond]]: 0, [[Nanosecond]]: + // 0 }. + return {{0, 0, result}, {0, 0, 0, 0, 0, 0}}; + // 12. If unit is "hour", then + case Unit::kHour: + // a. Return ! BalanceTime(result, 0, 0, 0, 0, 0). + return BalanceTime({result, 0, 0, 0, 0, 0}); + // 13. If unit is "minute", then + case Unit::kMinute: + // a. Return ! BalanceTime(hour, result, 0, 0, 0, 0). + return BalanceTime({time.hour, result, 0, 0, 0, 0}); + // 14. If unit is "second", then + case Unit::kSecond: + // a. Return ! BalanceTime(hour, minute, result, 0, 0, 0). + return BalanceTime({time.hour, time.minute, result, 0, 0, 0}); + // 15. If unit is "millisecond", then + case Unit::kMillisecond: + // a. Return ! BalanceTime(hour, minute, second, result, 0, 0). + return BalanceTime({time.hour, time.minute, time.second, result, 0, 0}); + // 16. If unit is "microsecond", then + case Unit::kMicrosecond: + // a. Return ! BalanceTime(hour, minute, second, millisecond, result, 0). + return BalanceTime( + {time.hour, time.minute, time.second, time.millisecond, result, 0}); + default: + // 17. Assert: unit is "nanosecond". + DCHECK_EQ(unit, Unit::kNanosecond); + // 18. Return ! BalanceTime(hour, minute, second, millisecond, + // microsecond, result). + return BalanceTime({time.hour, time.minute, time.second, time.millisecond, + time.microsecond, result}); + } +} + +DateTimeRecordCommon RoundTime(Isolate* isolate, const TimeRecordCommon& time, + double increment, Unit unit, + RoundingMode rounding_mode) { + TEMPORAL_ENTER_FUNC(); + + // 3-a. If dayLengthNs is not present, set it to 8.64 × 10^13. + return RoundTime(isolate, time, increment, unit, rounding_mode, + 86400000000000LLU); +} + +// GetOption wihle the types is << Number, String >> and values is empty. +// #sec-getoption +MaybeHandle GetOption_NumberOrString(Isolate* isolate, + Handle options, + Handle property, + Handle fallback, + const char* method) { + // 3. Let value be ? Get(options, property). + Handle value; + ASSIGN_RETURN_ON_EXCEPTION( + isolate, value, JSReceiver::GetProperty(isolate, options, property), + Object); + // 4. If value is undefined, return fallback. + if (value->IsUndefined()) { + return fallback; + } + // 5. If types contains Type(value), then + // a. Let type be Type(value). + // 6. Else, + // a. Let type be the last element of types. + // 7. If type is Boolean, then + // a. Set value to ! ToBoolean(value). + // 8. Else if type is Number, then + if (value->IsNumber()) { + // a. Set value to ? ToNumber(value). + ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::ToNumber(isolate, value), + Object); + // b. If value is NaN, throw a RangeError exception. + if (value->IsNaN()) { + THROW_NEW_ERROR( + isolate, + NewRangeError(MessageTemplate::kPropertyValueOutOfRange, property), + Object); + } + return value; + } + // 9. Else, + // a. Set value to ? ToString(value). + ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::ToString(isolate, value), + Object); + return value; +} + +// In #sec-temporal-tosecondsstringprecision +// ToSecondsStringPrecision ( normalizedOptions ) +// 8. Let digits be ? GetStringOrNumberOption(normalizedOptions, +// "fractionalSecondDigits", « "auto" », 0, 9, "auto"). +Maybe GetFractionalSecondDigits(Isolate* isolate, + Handle options, + const char* method_name) { + Factory* factory = isolate->factory(); + // 2. Let value be ? GetOption(options, property, « Number, String », empty, + // fallback). + Handle value; + ASSIGN_RETURN_ON_EXCEPTION_VALUE( + isolate, value, + GetOption_NumberOrString(isolate, options, + factory->fractionalSecondDigits_string(), + factory->auto_string(), method_name), + Nothing()); + + // 3. If Type(value) is Number, then + if (value->IsNumber()) { + // a. If value < minimum or value > maximum, throw a RangeError exception. + double value_num = value->Number(); + if (value_num < 0 || value_num > 9) { + THROW_NEW_ERROR_RETURN_VALUE( + isolate, + NewRangeError(MessageTemplate::kPropertyValueOutOfRange, + factory->fractionalSecondDigits_string()), + Nothing()); + } + // b. Return floor(ℝ(value)). + int32_t v = std::floor(value_num); + return Just(static_cast(v)); + } + // 4. Assert: Type(value) is String. + DCHECK(value->IsString()); + // 5. If stringValues does not contain value, throw a RangeError exception. + Handle string_value = Handle::cast(value); + if (!String::Equals(isolate, string_value, factory->auto_string())) { + THROW_NEW_ERROR_RETURN_VALUE( + isolate, + NewRangeError(MessageTemplate::kPropertyValueOutOfRange, + factory->fractionalSecondDigits_string()), + Nothing()); + } + // 6. Return value. + return Just(Precision::kAuto); +} + +// #sec-temporal-tosecondsstringprecision +struct StringPrecision { + Precision precision; + Unit unit; + double increment; +}; + +// #sec-temporal-tosecondsstringprecision +Maybe ToSecondsStringPrecision( + Isolate* isolate, Handle normalized_options, + const char* method_name) { + // 1. Let smallestUnit be ? ToSmallestTemporalUnit(normalizedOptions, « + // "year", "month", "week", "day", "hour" », undefined). + Unit smallest_unit; + MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE( + isolate, smallest_unit, + ToSmallestTemporalUnit( + isolate, normalized_options, + std::set({Unit::kYear, Unit::kMonth, Unit::kWeek, Unit::kDay, + Unit::kHour}), + Unit::kNotPresent, method_name), + Nothing()); + + switch (smallest_unit) { + // 2. If smallestUnit is "minute", then + case Unit::kMinute: + // a. Return the new Record { [[Precision]]: "minute", [[Unit]]: "minute", + // [[Increment]]: 1 }. + return Just(StringPrecision({Precision::kMinute, Unit::kMinute, 1})); + // 3. If smallestUnit is "second", then + case Unit::kSecond: + // a. Return the new Record { [[Precision]]: 0, [[Unit]]: "second", + // [[Increment]]: 1 }. + return Just(StringPrecision({Precision::k0, Unit::kSecond, 1})); + // 4. If smallestUnit is "millisecond", then + case Unit::kMillisecond: + // a. Return the new Record { [[Precision]]: 3, [[Unit]]: "millisecond", + // [[Increment]]: 1 }. + return Just(StringPrecision({Precision::k3, Unit::kMillisecond, 1})); + // 5. If smallestUnit is "microsecond", then + case Unit::kMicrosecond: + // a. Return the new Record { [[Precision]]: 6, [[Unit]]: "microsecond", + // [[Increment]]: 1 }. + return Just(StringPrecision({Precision::k6, Unit::kMicrosecond, 1})); + // 6. If smallestUnit is "nanosecond", then + case Unit::kNanosecond: + // a. Return the new Record { [[Precision]]: 9, [[Unit]]: "nanosecond", + // [[Increment]]: 1 }. + return Just(StringPrecision({Precision::k9, Unit::kNanosecond, 1})); + default: + break; + } + // 7. Assert: smallestUnit is undefined. + DCHECK(smallest_unit == Unit::kNotPresent); + // 8. Let digits be ? GetStringOrNumberOption(normalizedOptions, + // "fractionalSecondDigits", « "auto" », 0, 9, "auto"). + Precision digits; + MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE( + isolate, digits, + GetFractionalSecondDigits(isolate, normalized_options, method_name), + Nothing()); + + switch (digits) { + // 9. If digits is "auto", then + case Precision::kAuto: + // a. Return the new Record { [[Precision]]: "auto", [[Unit]]: + // "nanosecond", [[Increment]]: 1 }. + return Just(StringPrecision({Precision::kAuto, Unit::kNanosecond, 1})); + // 10. If digits is 0, then + case Precision::k0: + // a. Return the new Record { [[Precision]]: 0, [[Unit]]: "second", + // [[Increment]]: 1 }. + return Just(StringPrecision({Precision::k0, Unit::kSecond, 1})); + // 11. If digits is 1, 2, or 3, then + // a. Return the new Record { [[Precision]]: digits, [[Unit]]: + // "millisecond", [[Increment]]: 10^3 − digits }. + case Precision::k1: + return Just(StringPrecision({Precision::k1, Unit::kMillisecond, 100})); + case Precision::k2: + return Just(StringPrecision({Precision::k2, Unit::kMillisecond, 10})); + case Precision::k3: + return Just(StringPrecision({Precision::k3, Unit::kMillisecond, 1})); + // 12. If digits is 4, 5, or 6, then + // a. Return the new Record { [[Precision]]: digits, [[Unit]]: + // "microsecond", [[Increment]]: 10^6 − digits }. + case Precision::k4: + return Just(StringPrecision({Precision::k4, Unit::kMicrosecond, 100})); + case Precision::k5: + return Just(StringPrecision({Precision::k5, Unit::kMicrosecond, 10})); + case Precision::k6: + return Just(StringPrecision({Precision::k6, Unit::kMicrosecond, 1})); + // 13. Assert: digits is 7, 8, or 9. + // 14. Return the new Record { [[Precision]]: digits, [[Unit]]: + // "nanosecond", [[Increment]]: 10^9 − digits }. + case Precision::k7: + return Just(StringPrecision({Precision::k7, Unit::kNanosecond, 100})); + case Precision::k8: + return Just(StringPrecision({Precision::k8, Unit::kNanosecond, 10})); + case Precision::k9: + return Just(StringPrecision({Precision::k9, Unit::kNanosecond, 1})); + default: + UNREACHABLE(); + } +} + +} // namespace + +// #sec-temporal.plaintime.prototype.tostring +MaybeHandle JSTemporalPlainTime::ToString( + Isolate* isolate, Handle temporal_time, + Handle options_obj) { + const char* method_name = "Temporal.PlainTime.prototype.toString"; + // 1. Let temporalTime be the this value. + // 2. Perform ? RequireInternalSlot(temporalTime, + // [[InitializedTemporalTime]]). + // 3. Set options to ? GetOptionsObject(options). + Handle options; + ASSIGN_RETURN_ON_EXCEPTION( + isolate, options, GetOptionsObject(isolate, options_obj, method_name), + String); + + // 4. Let precision be ? ToSecondsStringPrecision(options). + StringPrecision precision; + MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE( + isolate, precision, + ToSecondsStringPrecision(isolate, options, method_name), + Handle()); + + // 5. Let roundingMode be ? ToTemporalRoundingMode(options, "trunc"). + RoundingMode rounding_mode; + MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE( + isolate, rounding_mode, + ToTemporalRoundingMode(isolate, options, RoundingMode::kTrunc, + method_name), + Handle()); + + // 6. Let roundResult be ! RoundTime(temporalTime.[[ISOHour]], + // temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], + // temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], + // temporalTime.[[ISONanosecond]], precision.[[Increment]], + // precision.[[Unit]], roundingMode). + + DateTimeRecordCommon round_result = RoundTime( + isolate, + {temporal_time->iso_hour(), temporal_time->iso_minute(), + temporal_time->iso_second(), temporal_time->iso_millisecond(), + temporal_time->iso_microsecond(), temporal_time->iso_nanosecond()}, + precision.increment, precision.unit, rounding_mode); + // 7. Return ! TemporalTimeToString(roundResult.[[Hour]], + // roundResult.[[Minute]], roundResult.[[Second]], + // roundResult.[[Millisecond]], roundResult.[[Microsecond]], + // roundResult.[[Nanosecond]], precision.[[Precision]]). + return TemporalTimeToString(isolate, round_result.time, precision.precision); +} + // #sec-temporal.zoneddatetime MaybeHandle JSTemporalZonedDateTime::Constructor( Isolate* isolate, Handle target, Handle new_target, diff --git a/src/objects/js-temporal-objects.h b/src/objects/js-temporal-objects.h index b77ab178b6..2f414244b0 100644 --- a/src/objects/js-temporal-objects.h +++ b/src/objects/js-temporal-objects.h @@ -536,6 +536,16 @@ class JSTemporalPlainTime V8_WARN_UNUSED_RESULT static MaybeHandle ToJSON( Isolate* isolate, Handle plain_time); + // #sec-temporal.plaintime.prototype.tostring + V8_WARN_UNUSED_RESULT static MaybeHandle ToString( + Isolate* isolate, Handle plain_time, + Handle options); + + // #sec-temporal.plaintime.prototype.tolocalestring + V8_WARN_UNUSED_RESULT static MaybeHandle ToLocaleString( + Isolate* isolate, Handle plain_time, + Handle locales, Handle options); + DECL_PRINTER(JSTemporalPlainTime) DEFINE_TORQUE_GENERATED_JS_TEMPORAL_HOUR_MINUTE_SECOND() diff --git a/test/test262/test262.status b/test/test262/test262.status index c932b525df..c8fc8ac430 100644 --- a/test/test262/test262.status +++ b/test/test262/test262.status @@ -1019,21 +1019,12 @@ 'built-ins/Temporal/PlainTime/prototype/subtract/non-integer-throws-rangeerror': [FAIL], 'built-ins/Temporal/PlainTime/prototype/subtract/order-of-operations': [FAIL], 'built-ins/Temporal/PlainTime/prototype/subtract/subclassing-ignored': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toLocaleString/branding': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toLocaleString/return-string': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toString/branding': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-invalid-string': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-nan': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-non-integer': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-out-of-range': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-undefined': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-wrong-type': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/options-undefined': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toString/roundingmode-invalid-string': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/roundingmode-undefined': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/roundingmode-wrong-type': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toString/smallestunit-invalid-string': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toString/smallestunit-plurals-accepted': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/smallestunit-undefined': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/smallestunit-valid-units': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/smallestunit-wrong-type': [FAIL], @@ -1680,7 +1671,6 @@ 'built-ins/Temporal/PlainTime/prototype/toString/basic': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-auto': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/fractionalseconddigits-number': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toString/options-invalid': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/rounding-cross-midnight': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/roundingmode-ceil': [FAIL], 'built-ins/Temporal/PlainTime/prototype/toString/roundingmode-floor': [FAIL], @@ -1920,7 +1910,6 @@ 'built-ins/Temporal/PlainTime/prototype/round/options-wrong-type': [FAIL], 'built-ins/Temporal/PlainTime/prototype/round/roundto-invalid-string': [FAIL], 'built-ins/Temporal/PlainTime/prototype/since/options-wrong-type': [FAIL], - 'built-ins/Temporal/PlainTime/prototype/toString/options-wrong-type': [FAIL], 'built-ins/Temporal/PlainTime/prototype/until/options-wrong-type': [FAIL], 'built-ins/Temporal/PlainYearMonth/prototype/add/options-wrong-type': [FAIL], 'built-ins/Temporal/PlainYearMonth/prototype/since/options-wrong-type': [FAIL],