[Temporal] Add PlainTime toString and non-intl toLocaleString
Also implement AOs: ToTemporalRoundingMode, ToSmallestTemporalUnit, RoundNumberToIncrement, RoundTime, ToSecondsStringPrecision Spec Text: https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.tostring https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.tolocalestring https://tc39.es/proposal-temporal/#sec-temporal-totemporalroundingmode https://tc39.es/proposal-temporal/#sec-temporal-tosmallesttemporalunit https://tc39.es/proposal-temporal/#sec-temporal-roundnumbertoincrement https://tc39.es/proposal-temporal/#sec-temporal-roundtime https://tc39.es/proposal-temporal/#sec-temporal-tosecondsstringprecision Bug: v8:11544 Change-Id: I47ea27e966232e89bab48bf15a48c2c00ce5e160 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3665937 Reviewed-by: Adam Klein <adamk@chromium.org> Commit-Queue: Frank Tang <ftang@chromium.org> Cr-Commit-Position: refs/heads/main@{#80792}
This commit is contained in:
parent
05874e44e5
commit
8ea33c9f54
@ -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) {
|
||||
|
@ -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] }") \
|
||||
|
@ -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<String> TemporalTimeToString(Isolate* isolate,
|
||||
Handle<JSTemporalPlainTime> 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<String> TemporalTimeToString(Isolate* isolate,
|
||||
Handle<JSTemporalPlainTime> 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<bool> ToTemporalOverflowForSideEffects(Isolate* isolate,
|
||||
return Just(true);
|
||||
}
|
||||
|
||||
// sec-temporal-totemporalroundingmode
|
||||
Maybe<RoundingMode> ToTemporalRoundingMode(Isolate* isolate,
|
||||
Handle<JSReceiver> options,
|
||||
RoundingMode fallback,
|
||||
const char* method_name) {
|
||||
return GetStringOption<RoundingMode>(
|
||||
isolate, options, "roundingMode", method_name,
|
||||
{"ceil", "floor", "trunc", "halfExpand"},
|
||||
{RoundingMode::kCeil, RoundingMode::kFloor, RoundingMode::kTrunc,
|
||||
RoundingMode::kHalfExpand},
|
||||
fallback);
|
||||
}
|
||||
|
||||
// #sec-temporal-totemporaldisambiguation
|
||||
Maybe<Disambiguation> ToTemporalDisambiguation(Isolate* isolate,
|
||||
Handle<JSReceiver> options,
|
||||
@ -4358,6 +4383,54 @@ Maybe<TimeRecordCommon> ToTemporalTimeRecord(
|
||||
method_name);
|
||||
}
|
||||
|
||||
// #sec-temporal-tolargesttemporalunit
|
||||
Maybe<Unit> ToSmallestTemporalUnit(Isolate* isolate,
|
||||
Handle<JSReceiver> normalized_options,
|
||||
const std::set<Unit>& 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<Unit>(
|
||||
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<Unit>());
|
||||
// 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<Unit>());
|
||||
}
|
||||
// 5. Return smallestUnit.
|
||||
return Just(smallest_unit);
|
||||
}
|
||||
|
||||
// #sec-temporal-mergelargestunitoption
|
||||
MaybeHandle<JSObject> MergeLargestUnitOption(Isolate* isolate,
|
||||
Handle<Object> options_obj,
|
||||
@ -10359,6 +10432,415 @@ MaybeHandle<String> JSTemporalPlainTime::ToJSON(
|
||||
return TemporalTimeToString(isolate, temporal_time, Precision::kAuto);
|
||||
}
|
||||
|
||||
// #sup-temporal.plaintime.prototype.tolocalestring
|
||||
MaybeHandle<String> JSTemporalPlainTime::ToLocaleString(
|
||||
Isolate* isolate, Handle<JSTemporalPlainTime> temporal_time,
|
||||
Handle<Object> locales, Handle<Object> 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<double>(time.nanosecond) / 100000000.0 +
|
||||
static_cast<double>(time.microsecond) / 1000000.0 +
|
||||
static_cast<double>(time.millisecond) / 1000.0 +
|
||||
static_cast<double>(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<Object> GetOption_NumberOrString(Isolate* isolate,
|
||||
Handle<JSReceiver> options,
|
||||
Handle<String> property,
|
||||
Handle<Object> fallback,
|
||||
const char* method) {
|
||||
// 3. Let value be ? Get(options, property).
|
||||
Handle<Object> 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<Precision> GetFractionalSecondDigits(Isolate* isolate,
|
||||
Handle<JSReceiver> options,
|
||||
const char* method_name) {
|
||||
Factory* factory = isolate->factory();
|
||||
// 2. Let value be ? GetOption(options, property, « Number, String », empty,
|
||||
// fallback).
|
||||
Handle<Object> value;
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, value,
|
||||
GetOption_NumberOrString(isolate, options,
|
||||
factory->fractionalSecondDigits_string(),
|
||||
factory->auto_string(), method_name),
|
||||
Nothing<Precision>());
|
||||
|
||||
// 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<Precision>());
|
||||
}
|
||||
// b. Return floor(ℝ(value)).
|
||||
int32_t v = std::floor(value_num);
|
||||
return Just(static_cast<Precision>(v));
|
||||
}
|
||||
// 4. Assert: Type(value) is String.
|
||||
DCHECK(value->IsString());
|
||||
// 5. If stringValues does not contain value, throw a RangeError exception.
|
||||
Handle<String> string_value = Handle<String>::cast(value);
|
||||
if (!String::Equals(isolate, string_value, factory->auto_string())) {
|
||||
THROW_NEW_ERROR_RETURN_VALUE(
|
||||
isolate,
|
||||
NewRangeError(MessageTemplate::kPropertyValueOutOfRange,
|
||||
factory->fractionalSecondDigits_string()),
|
||||
Nothing<Precision>());
|
||||
}
|
||||
// 6. Return value.
|
||||
return Just(Precision::kAuto);
|
||||
}
|
||||
|
||||
// #sec-temporal-tosecondsstringprecision
|
||||
struct StringPrecision {
|
||||
Precision precision;
|
||||
Unit unit;
|
||||
double increment;
|
||||
};
|
||||
|
||||
// #sec-temporal-tosecondsstringprecision
|
||||
Maybe<StringPrecision> ToSecondsStringPrecision(
|
||||
Isolate* isolate, Handle<JSReceiver> 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>({Unit::kYear, Unit::kMonth, Unit::kWeek, Unit::kDay,
|
||||
Unit::kHour}),
|
||||
Unit::kNotPresent, method_name),
|
||||
Nothing<StringPrecision>());
|
||||
|
||||
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<StringPrecision>());
|
||||
|
||||
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<String> JSTemporalPlainTime::ToString(
|
||||
Isolate* isolate, Handle<JSTemporalPlainTime> temporal_time,
|
||||
Handle<Object> 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<JSReceiver> 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<String>());
|
||||
|
||||
// 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<String>());
|
||||
|
||||
// 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> JSTemporalZonedDateTime::Constructor(
|
||||
Isolate* isolate, Handle<JSFunction> target, Handle<HeapObject> new_target,
|
||||
|
@ -536,6 +536,16 @@ class JSTemporalPlainTime
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToJSON(
|
||||
Isolate* isolate, Handle<JSTemporalPlainTime> plain_time);
|
||||
|
||||
// #sec-temporal.plaintime.prototype.tostring
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToString(
|
||||
Isolate* isolate, Handle<JSTemporalPlainTime> plain_time,
|
||||
Handle<Object> options);
|
||||
|
||||
// #sec-temporal.plaintime.prototype.tolocalestring
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToLocaleString(
|
||||
Isolate* isolate, Handle<JSTemporalPlainTime> plain_time,
|
||||
Handle<Object> locales, Handle<Object> options);
|
||||
|
||||
DECL_PRINTER(JSTemporalPlainTime)
|
||||
|
||||
DEFINE_TORQUE_GENERATED_JS_TEMPORAL_HOUR_MINUTE_SECOND()
|
||||
|
@ -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],
|
||||
|
Loading…
Reference in New Issue
Block a user