[Temporal] Add Instant.prototype.(add|subtract)

Spec Text:
https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.add
https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.subtract

Also fix bug in IsValidEpochNanoseconds

Bug: v8:11544
Change-Id: Ied605c9de4ee38a18e2356a89e3a69d534a004d1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3617394
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: Adam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80983}
This commit is contained in:
Frank Tang 2022-06-07 15:49:26 -07:00 committed by V8 LUCI CQ
parent c8419529aa
commit fdde51c674
5 changed files with 99 additions and 42 deletions

View File

@ -100,10 +100,6 @@ TO_BE_IMPLEMENTED(TemporalDurationPrototypeToLocaleString)
TO_BE_IMPLEMENTED(TemporalDurationPrototypeToString)
/* Temporal.Instant */
/* Temporal #sec-temporal.instant.prototype.add */
TO_BE_IMPLEMENTED(TemporalInstantPrototypeAdd)
/* Temporal #sec-temporal.instant.prototype.subtract */
TO_BE_IMPLEMENTED(TemporalInstantPrototypeSubtract)
/* Temporal #sec-temporal.instant.prototype.until */
TO_BE_IMPLEMENTED(TemporalInstantPrototypeUntil)
/* Temporal #sec-temporal.instant.prototype.since */
@ -660,6 +656,8 @@ TEMPORAL_GET_BIGINT_AFTER_DIVID(Instant, EpochMicroseconds, nanoseconds, 1000,
epochMicroseconds)
TEMPORAL_PROTOTYPE_METHOD1(Instant, ToZonedDateTime, toZonedDateTime)
TEMPORAL_PROTOTYPE_METHOD1(Instant, ToZonedDateTimeISO, toZonedDateTimeISO)
TEMPORAL_PROTOTYPE_METHOD1(Instant, Add, add)
TEMPORAL_PROTOTYPE_METHOD1(Instant, Subtract, subtract)
// Calendar
TEMPORAL_CONSTRUCTOR1(Calendar)

View File

@ -2525,7 +2525,7 @@ MaybeHandle<JSTemporalPlainTime> ToTemporalTime(Isolate* isolate,
// This function implement
// "For each row of Table 8, except the header row, in table order, do"
// loop. It is designed to be used to implement the common part of
// ToPartialDuration, ToLimitedTemporalDuration, ToTemporalDurationRecord
// ToPartialDuration, ToTemporalDurationRecord
Maybe<bool> IterateDurationRecordFieldsTable(
Isolate* isolate, Handle<JSReceiver> temporal_duration_like,
Maybe<bool> (*RowFunction)(Isolate*,
@ -5426,13 +5426,22 @@ MaybeHandle<BigInt> AddInstant(Isolate* isolate,
bool IsValidEpochNanoseconds(Isolate* isolate,
Handle<BigInt> epoch_nanoseconds) {
TEMPORAL_ENTER_FUNC();
// nsMinInstant = -nsMaxInstant = -8.64 × 10^21
constexpr double kNsMinInstant = -8.64e21;
// nsMaxInstant = 10^8 × nsPerDay = 8.64 × 1021
constexpr double kNsMaxInstant = 8.64e21;
// 1. Assert: Type(epochNanoseconds) is BigInt.
// 2. If epochNanoseconds < 86400 × 10^17 or epochNanoseconds > 86400 ×
// 10^17, then a. Return false.
// 3. Return true.
int64_t ns = epoch_nanoseconds->AsInt64();
return !(ns < -86400 * 1e17 || ns > 86400 * 1e17);
// 2. If (epochNanoseconds) < nsMinInstant or (epochNanoseconds) >
// nsMaxInstant, then
if (BigInt::CompareToDouble(epoch_nanoseconds, kNsMinInstant) ==
ComparisonResult::kLessThan ||
BigInt::CompareToDouble(epoch_nanoseconds, kNsMaxInstant) ==
ComparisonResult::kGreaterThan) {
// a. Return false.
return false;
}
return true;
}
Handle<BigInt> GetEpochFromISOParts(Isolate* isolate,
@ -7381,10 +7390,11 @@ MaybeHandle<JSTemporalPlainMonthDay> JSTemporalCalendar::MonthDayFromFields(
JSTemporalPlainMonthDay);
// 6. Let result be ? ISOMonthDayFromFields(fields, options).
if (calendar->calendar_index() == 0) {
Maybe<DateRecordCommon> maybe_result =
ISOMonthDayFromFields(isolate, fields, options, method_name);
MAYBE_RETURN(maybe_result, Handle<JSTemporalPlainMonthDay>());
DateRecordCommon result = maybe_result.FromJust();
DateRecordCommon result;
MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, result,
ISOMonthDayFromFields(isolate, fields, options, method_name),
Handle<JSTemporalPlainMonthDay>());
// 7. Return ? CreateTemporalMonthDay(result.[[Month]], result.[[Day]],
// calendar, result.[[ReferenceISOYear]]).
return CreateTemporalMonthDay(isolate, result.month, result.day, calendar,
@ -12133,6 +12143,73 @@ MaybeHandle<JSTemporalZonedDateTime> JSTemporalInstant::ToZonedDateTimeISO(
calendar);
}
namespace {
// #sec-temporal-adddurationtoorsubtractdurationfrominstant
MaybeHandle<JSTemporalInstant> AddDurationToOrSubtractDurationFromInstant(
Isolate* isolate, Arithmetic operation, Handle<JSTemporalInstant> handle,
Handle<Object> temporal_duration_like, const char* method_name) {
TEMPORAL_ENTER_FUNC();
// 1. If operation is subtract, let sign be -1. Otherwise, let sign be 1.
double sign = operation == Arithmetic::kSubtract ? -1.0 : 1.0;
// See https://github.com/tc39/proposal-temporal/pull/2253
// 2. Let duration be ? ToTemporalDurationRecord(temporalDurationLike).
DurationRecord duration;
MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate, duration,
temporal::ToTemporalDurationRecord(isolate, temporal_duration_like,
method_name),
Handle<JSTemporalInstant>());
TimeDurationRecord& time_duration = duration.time_duration;
if (time_duration.days != 0 || duration.months != 0 || duration.weeks != 0 ||
duration.years != 0) {
THROW_NEW_ERROR_RETURN_VALUE(isolate,
NEW_TEMPORAL_INVALID_ARG_RANGE_ERROR(),
Handle<JSTemporalInstant>());
}
// 3. Let ns be ? AddInstant(instant.[[EpochNanoseconds]], sign x
// duration.[[Hours]], sign x duration.[[Minutes]], sign x
// duration.[[Seconds]], sign x duration.[[Milliseconds]], sign x
// duration.[[Microseconds]], sign x duration.[[Nanoseconds]]).
Handle<BigInt> ns;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, ns,
AddInstant(
isolate, Handle<BigInt>(handle->nanoseconds(), isolate),
{0, sign * time_duration.hours, sign * time_duration.minutes,
sign * time_duration.seconds, sign * time_duration.milliseconds,
sign * time_duration.microseconds,
sign * time_duration.nanoseconds}),
JSTemporalInstant);
// 4. Return ! CreateTemporalInstant(ns).
return temporal::CreateTemporalInstant(isolate, ns);
}
} // namespace
// #sec-temporal.instant.prototype.add
MaybeHandle<JSTemporalInstant> JSTemporalInstant::Add(
Isolate* isolate, Handle<JSTemporalInstant> handle,
Handle<Object> temporal_duration_like) {
TEMPORAL_ENTER_FUNC();
return AddDurationToOrSubtractDurationFromInstant(
isolate, Arithmetic::kAdd, handle, temporal_duration_like,
"Temporal.Instant.prototype.add");
}
// #sec-temporal.instant.prototype.subtract
MaybeHandle<JSTemporalInstant> JSTemporalInstant::Subtract(
Isolate* isolate, Handle<JSTemporalInstant> handle,
Handle<Object> temporal_duration_like) {
TEMPORAL_ENTER_FUNC();
return AddDurationToOrSubtractDurationFromInstant(
isolate, Arithmetic::kSubtract, handle, temporal_duration_like,
"Temporal.Instant.prototype.subtract");
}
namespace temporal {
// Step iii and iv of #sec-temporal.calendar.prototype.fields

View File

@ -256,6 +256,16 @@ class JSTemporalInstant
Isolate* isolate, Handle<JSTemporalInstant> instant,
Handle<Object> other);
// #sec-temporal.instant.prototype.add
V8_WARN_UNUSED_RESULT static MaybeHandle<JSTemporalInstant> Add(
Isolate* isolate, Handle<JSTemporalInstant> instant,
Handle<Object> temporal_duration_like);
// #sec-temporal.instant.prototype.subtract
V8_WARN_UNUSED_RESULT static MaybeHandle<JSTemporalInstant> Subtract(
Isolate* isolate, Handle<JSTemporalInstant> instant,
Handle<Object> temporal_duration_like);
DECL_PRINTER(JSTemporalInstant)
TQ_OBJECT_CONSTRUCTORS(JSTemporalInstant)

View File

@ -48,13 +48,9 @@
'temporal/calendar-week-of-year': [FAIL],
'temporal/duration-add': [FAIL],
'temporal/duration-to-json': [FAIL],
'temporal/instant-add': [FAIL],
'temporal/instant-constructor': [FAIL],
'temporal/instant-from-epoch-microseconds': [FAIL],
'temporal/instant-from-epoch-milliseconds': [FAIL],
'temporal/instant-from-epoch-nanoseconds': [FAIL],
'temporal/instant-from-epoch-seconds': [FAIL],
'temporal/instant-subtract': [FAIL],
'temporal/instant-to-json': [FAIL],
'temporal/instant-toJSON': [FAIL],
'temporal/plain-date-time-add': [FAIL],

View File

@ -542,15 +542,6 @@
'built-ins/Temporal/Instant/compare/instant-string': [FAIL],
'built-ins/Temporal/Instant/from/instant-string': [FAIL],
'built-ins/Temporal/Instant/from/timezone-custom': [FAIL],
'built-ins/Temporal/Instant/prototype/add/argument-string': [FAIL],
'built-ins/Temporal/Instant/prototype/add/argument-string-negative-fractional-units': [FAIL],
'built-ins/Temporal/Instant/prototype/add/branding': [FAIL],
'built-ins/Temporal/Instant/prototype/add/infinity-throws-rangeerror': [FAIL],
'built-ins/Temporal/Instant/prototype/add/negative-infinity-throws-rangeerror': [FAIL],
'built-ins/Temporal/Instant/prototype/add/non-integer-throws-rangeerror': [FAIL],
'built-ins/Temporal/Instant/prototype/add/order-of-operations': [FAIL],
'built-ins/Temporal/Instant/prototype/add/result-out-of-range': [FAIL],
'built-ins/Temporal/Instant/prototype/add/subclassing-ignored': [FAIL],
'built-ins/Temporal/Instant/prototype/equals/argument-wrong-type': [FAIL],
'built-ins/Temporal/Instant/prototype/equals/instant-string': [FAIL],
'built-ins/Temporal/Instant/prototype/round/branding': [FAIL],
@ -590,15 +581,6 @@
'built-ins/Temporal/Instant/prototype/since/smallestunit-plurals-accepted': [FAIL],
'built-ins/Temporal/Instant/prototype/since/smallestunit-undefined': [FAIL],
'built-ins/Temporal/Instant/prototype/since/smallestunit-wrong-type': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/argument-string': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/argument-string-negative-fractional-units': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/branding': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/infinity-throws-rangeerror': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/negative-infinity-throws-rangeerror': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/non-integer-throws-rangeerror': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/order-of-operations': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/result-out-of-range': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/subclassing-ignored': [FAIL],
'built-ins/Temporal/Instant/prototype/toJSON/basic': [FAIL],
'built-ins/Temporal/Instant/prototype/toJSON/branding': [FAIL],
'built-ins/Temporal/Instant/prototype/toJSON/negative-epochnanoseconds': [FAIL],
@ -1437,10 +1419,8 @@
'built-ins/Temporal/Duration/prototype/toString/fractionalseconddigits-exact-number-of-digits': [FAIL],
'built-ins/Temporal/Duration/prototype/total/calendar-possibly-required': [FAIL],
'built-ins/Temporal/Duration/prototype/total/year-zero': [FAIL],
'built-ins/Temporal/Instant/prototype/add/argument-string-fractional-units-rounding-mode': [FAIL],
'built-ins/Temporal/Instant/prototype/since/largestunit-smallestunit-mismatch': [FAIL],
'built-ins/Temporal/Instant/prototype/since/year-zero': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/argument-string-fractional-units-rounding-mode': [FAIL],
'built-ins/Temporal/Instant/prototype/until/largestunit-smallestunit-mismatch': [FAIL],
'built-ins/Temporal/Instant/prototype/until/year-zero': [FAIL],
'built-ins/Temporal/PlainDate/prototype/since/days-in-month': [FAIL],
@ -1636,10 +1616,6 @@
'built-ins/Temporal/Duration/compare/twenty-five-hour-day': [FAIL],
'built-ins/Temporal/Duration/prototype/toJSON/basic': [FAIL],
'built-ins/Temporal/Duration/prototype/toString/balance': [FAIL],
'built-ins/Temporal/Instant/prototype/add/basic': [FAIL],
'built-ins/Temporal/Instant/prototype/add/disallowed-duration-units': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/basic': [FAIL],
'built-ins/Temporal/Instant/prototype/subtract/disallowed-duration-units': [FAIL],
'built-ins/Temporal/PlainDate/prototype/since/argument-string-invalid': [FAIL],
'built-ins/Temporal/PlainDate/prototype/until/argument-string-invalid': [FAIL],
'built-ins/Temporal/PlainDateTime/datetime-math': [FAIL],