From 6d33cb89a4eee84180c2516d5966ae38f272c0a1 Mon Sep 17 00:00:00 2001 From: Frank Tang Date: Mon, 6 Jun 2022 10:02:57 -0700 Subject: [PATCH] [Temporal] Add Instant.(compare|prototype.equals) Also implement AO: CompareEpochNanoseconds Spec Text: https://tc39.es/proposal-temporal/#sec-temporal.instant.compare https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.equals Bug: v8:11544 Change-Id: I953a890250ff0bf29cd24e4638bf17ceb5f9bb2f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3382057 Commit-Queue: Frank Tang Reviewed-by: Adam Klein Cr-Commit-Position: refs/heads/main@{#80959} --- src/builtins/builtins-temporal.cc | 15 ++++-- src/objects/js-temporal-objects.cc | 78 ++++++++++++++++++++++++++---- src/objects/js-temporal-objects.h | 10 ++++ test/mjsunit/mjsunit.status | 2 - test/test262/test262.status | 13 ----- 5 files changed, 89 insertions(+), 29 deletions(-) diff --git a/src/builtins/builtins-temporal.cc b/src/builtins/builtins-temporal.cc index 2fe4d39d00..3bf730c87d 100644 --- a/src/builtins/builtins-temporal.cc +++ b/src/builtins/builtins-temporal.cc @@ -104,8 +104,6 @@ TO_BE_IMPLEMENTED(TemporalDurationPrototypeToLocaleString) TO_BE_IMPLEMENTED(TemporalDurationPrototypeToString) /* Temporal.Instant */ -/* Temporal #sec-temporal.instant.compare */ -TO_BE_IMPLEMENTED(TemporalInstantCompare) /* Temporal #sec-temporal.instant.prototype.add */ TO_BE_IMPLEMENTED(TemporalInstantPrototypeAdd) /* Temporal #sec-temporal.instant.prototype.subtract */ @@ -116,8 +114,6 @@ TO_BE_IMPLEMENTED(TemporalInstantPrototypeUntil) TO_BE_IMPLEMENTED(TemporalInstantPrototypeSince) /* Temporal #sec-temporal.instant.prototype.round */ TO_BE_IMPLEMENTED(TemporalInstantPrototypeRound) -/* Temporal #sec-temporal.instant.prototype.equals */ -TO_BE_IMPLEMENTED(TemporalInstantPrototypeEquals) /* Temporal #sec-temporal.instant.prototype.tolocalestring */ TO_BE_IMPLEMENTED(TemporalInstantPrototypeToLocaleString) /* Temporal #sec-temporal.instant.prototype.tostring */ @@ -244,6 +240,15 @@ TO_BE_IMPLEMENTED(TemporalZonedDateTimePrototypeToLocaleString) JSTemporal##T ::METHOD(isolate, args.atOrUndefined(isolate, 1))); \ } +#define TEMPORAL_METHOD2(T, METHOD) \ + BUILTIN(Temporal##T##METHOD) { \ + HandleScope scope(isolate); \ + RETURN_RESULT_OR_FAILURE( \ + isolate, \ + JSTemporal##T ::METHOD(isolate, args.atOrUndefined(isolate, 1), \ + args.atOrUndefined(isolate, 2))); \ + } + #define TEMPORAL_GET(T, METHOD, field) \ BUILTIN(Temporal##T##Prototype##METHOD) { \ HandleScope scope(isolate); \ @@ -645,6 +650,8 @@ TEMPORAL_METHOD1(Instant, FromEpochMilliseconds) TEMPORAL_METHOD1(Instant, FromEpochMicroseconds) TEMPORAL_METHOD1(Instant, FromEpochNanoseconds) TEMPORAL_METHOD1(Instant, From) +TEMPORAL_METHOD2(Instant, Compare) +TEMPORAL_PROTOTYPE_METHOD1(Instant, Equals, equals) TEMPORAL_VALUE_OF(Instant) TEMPORAL_GET(Instant, EpochNanoseconds, nanoseconds) TEMPORAL_GET_NUMBER_AFTER_DIVID(Instant, EpochSeconds, nanoseconds, 1000000000, diff --git a/src/objects/js-temporal-objects.cc b/src/objects/js-temporal-objects.cc index f039ad1733..c36f55f881 100644 --- a/src/objects/js-temporal-objects.cc +++ b/src/objects/js-temporal-objects.cc @@ -2816,10 +2816,18 @@ MaybeHandle SystemZonedDateTime( return CreateTemporalZonedDateTime(isolate, ns, time_zone, calendar); } -#define COMPARE_RESULT_TO_SIGN(r) \ - ((r) == ComparisonResult::kEqual \ - ? 0 \ - : ((r) == ComparisonResult::kLessThan ? -1 : 1)) +int CompareResultToSign(ComparisonResult r) { + switch (r) { + case ComparisonResult::kEqual: + return 0; + case ComparisonResult::kLessThan: + return -1; + case ComparisonResult::kGreaterThan: + return 1; + case ComparisonResult::kUndefined: + UNREACHABLE(); + } +} // #sec-temporal-formattimezoneoffsetstring Handle FormatTimeZoneOffsetString(Isolate* isolate, @@ -5027,7 +5035,7 @@ Maybe NanosecondsToDays(Isolate* isolate, // 3. Let sign be ! ℝ(Sign(𝔽(nanoseconds))). ComparisonResult compare_result = BigInt::CompareToBigInt(nanoseconds, BigInt::FromInt64(isolate, 0)); - double sign = COMPARE_RESULT_TO_SIGN(compare_result); + double sign = CompareResultToSign(compare_result); // 4. Let dayLengthNs be 8.64 × 10^13. Handle day_length_ns = BigInt::FromInt64(isolate, 86400000000000LLU); // 5. If sign is 0, then @@ -5197,7 +5205,7 @@ Maybe NanosecondsToDays(Isolate* isolate, // c. If (nanoseconds − dayLengthNs) × sign ≥ 0, then compare_result = BigInt::CompareToBigInt(nanoseconds, day_length_ns); - if (sign * COMPARE_RESULT_TO_SIGN(compare_result) >= 0) { + if (sign * CompareResultToSign(compare_result) >= 0) { // i. Set nanoseconds to nanoseconds − dayLengthNs. ASSIGN_RETURN_ON_EXCEPTION_VALUE( isolate, nanoseconds, @@ -10612,8 +10620,6 @@ MaybeHandle JSTemporalPlainTime::ToPlainDateTime( namespace { -enum class Arithmetic { kAdd, kSubtract }; - // #sec-temporal-adddurationtoorsubtractdurationfromplaintime MaybeHandle AddDurationToOrSubtractDurationFromPlainTime( Isolate* isolate, Arithmetic operation, @@ -11081,6 +11087,19 @@ Maybe ToSecondsStringPrecision( } } +// #sec-temporal-compareepochnanoseconds +MaybeHandle CompareEpochNanoseconds(Isolate* isolate, Handle one, + Handle two) { + TEMPORAL_ENTER_FUNC(); + + // 1. If epochNanosecondsOne > epochNanosecondsTwo, return 1. + // 2. If epochNanosecondsOne < epochNanosecondsTwo, return -1. + // 3. Return 0. + return handle( + Smi::FromInt(CompareResultToSign(BigInt::CompareToBigInt(one, two))), + isolate); +} + } // namespace // #sec-temporal.plaintime.prototype.tostring @@ -11764,14 +11783,13 @@ MaybeHandle JSTemporalInstant::Constructor( Isolate* isolate, Handle target, Handle new_target, Handle epoch_nanoseconds_obj) { TEMPORAL_ENTER_FUNC(); - const char* method_name = "Temporal.Instant"; // 1. If NewTarget is undefined, then if (new_target->IsUndefined()) { // a. Throw a TypeError exception. THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kMethodInvokedOnWrongType, isolate->factory()->NewStringFromAsciiChecked( - method_name)), + "Temporal.Instant")), JSTemporalInstant); } // 2. Let epochNanoseconds be ? ToBigInt(epochNanoseconds). @@ -11877,6 +11895,46 @@ MaybeHandle JSTemporalInstant::FromEpochNanoseconds( return ScaleToNanosecondsVerifyAndMake(isolate, epoch_nanoseconds, 1); } +// #sec-temporal.instant.compare +MaybeHandle JSTemporalInstant::Compare(Isolate* isolate, + Handle one_obj, + Handle two_obj) { + TEMPORAL_ENTER_FUNC(); + const char* method_name = "Temporal.Instant.compare"; + // 1. Set one to ? ToTemporalInstant(one). + Handle one; + ASSIGN_RETURN_ON_EXCEPTION( + isolate, one, ToTemporalInstant(isolate, one_obj, method_name), Smi); + // 2. Set two to ? ToTemporalInstant(two). + Handle two; + ASSIGN_RETURN_ON_EXCEPTION( + isolate, two, ToTemporalInstant(isolate, two_obj, method_name), Smi); + // 3. Return 𝔽(! CompareEpochNanoseconds(one.[[Nanoseconds]], + // two.[[Nanoseconds]])). + return CompareEpochNanoseconds(isolate, handle(one->nanoseconds(), isolate), + handle(two->nanoseconds(), isolate)); +} + +// #sec-temporal.instant.prototype.equals +MaybeHandle JSTemporalInstant::Equals(Isolate* isolate, + Handle handle, + Handle other_obj) { + TEMPORAL_ENTER_FUNC(); + // 1. Let instant be the this value. + // 2. Perform ? RequireInternalSlot(instant, [[InitializedTemporalInstant]]). + // 3. Set other to ? ToTemporalInstant(other). + Handle other; + ASSIGN_RETURN_ON_EXCEPTION( + isolate, other, + ToTemporalInstant(isolate, other_obj, + "Temporal.Instant.prototype.equals"), + Oddball); + // 4. If instant.[[Nanoseconds]] ≠ other.[[Nanoseconds]], return false. + // 5. Return true. + return isolate->factory()->ToBoolean( + BigInt::EqualToBigInt(handle->nanoseconds(), other->nanoseconds())); +} + // #sec-temporal.instant.from MaybeHandle JSTemporalInstant::From(Isolate* isolate, Handle item) { diff --git a/src/objects/js-temporal-objects.h b/src/objects/js-temporal-objects.h index 546b320189..cffc990db2 100644 --- a/src/objects/js-temporal-objects.h +++ b/src/objects/js-temporal-objects.h @@ -246,6 +246,16 @@ class JSTemporalInstant ToZonedDateTimeISO(Isolate* isolate, Handle instant, Handle item); + // #sec-temporal.instant.compare + V8_WARN_UNUSED_RESULT static MaybeHandle Compare(Isolate* isolate, + Handle one, + Handle two); + + // #sec-temporal.instant.prototype.equals + V8_WARN_UNUSED_RESULT static MaybeHandle Equals( + Isolate* isolate, Handle instant, + Handle other); + DECL_PRINTER(JSTemporalInstant) TQ_OBJECT_CONSTRUCTORS(JSTemporalInstant) diff --git a/test/mjsunit/mjsunit.status b/test/mjsunit/mjsunit.status index 23d6fa40b7..774b043831 100644 --- a/test/mjsunit/mjsunit.status +++ b/test/mjsunit/mjsunit.status @@ -49,9 +49,7 @@ 'temporal/duration-add': [FAIL], 'temporal/duration-to-json': [FAIL], 'temporal/instant-add': [FAIL], - 'temporal/instant-compare': [FAIL], 'temporal/instant-constructor': [FAIL], - 'temporal/instant-equals': [FAIL], 'temporal/instant-from-epoch-microseconds': [FAIL], 'temporal/instant-from-epoch-milliseconds': [FAIL], 'temporal/instant-from-epoch-nanoseconds': [FAIL], diff --git a/test/test262/test262.status b/test/test262/test262.status index 42a0f17101..e868cf0378 100644 --- a/test/test262/test262.status +++ b/test/test262/test262.status @@ -347,8 +347,6 @@ 'built-ins/Temporal/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable': [FAIL], 'built-ins/Temporal/Duration/prototype/total/timezone-getpossibleinstantsfor-iterable': [FAIL], - 'built-ins/Temporal/Instant/from/instant-string-multiple-offsets': [SKIP], - # https://github.com/tc39/test262/issues/3262 'built-ins/Temporal/Duration/prototype/add/calendar-dateadd-called-with-options-undefined': [FAIL], 'built-ins/Temporal/Duration/prototype/subtract/calendar-dateadd-called-with-options-undefined': [FAIL], @@ -541,9 +539,7 @@ 'built-ins/Temporal/Duration/prototype/total/unit-plurals-accepted-string': [FAIL], 'built-ins/Temporal/Duration/prototype/total/unit-string-shorthand-string': [FAIL], 'built-ins/Temporal/Duration/prototype/total/unit-wrong-type': [FAIL], - 'built-ins/Temporal/Instant/compare/argument-zoneddatetime': [FAIL], 'built-ins/Temporal/Instant/compare/instant-string': [FAIL], - 'built-ins/Temporal/Instant/compare/instant-string-multiple-offsets': [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], @@ -556,10 +552,7 @@ '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/argument-zoneddatetime': [FAIL], - 'built-ins/Temporal/Instant/prototype/equals/branding': [FAIL], 'built-ins/Temporal/Instant/prototype/equals/instant-string': [FAIL], - 'built-ins/Temporal/Instant/prototype/equals/instant-string-multiple-offsets': [FAIL], 'built-ins/Temporal/Instant/prototype/round/branding': [FAIL], 'built-ins/Temporal/Instant/prototype/round/options-wrong-type': [FAIL], 'built-ins/Temporal/Instant/prototype/round/roundingincrement-nan': [FAIL], @@ -1470,9 +1463,7 @@ '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/compare/year-zero': [FAIL], 'built-ins/Temporal/Instant/prototype/add/argument-string-fractional-units-rounding-mode': [FAIL], - 'built-ins/Temporal/Instant/prototype/equals/year-zero': [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], @@ -1857,12 +1848,8 @@ 'built-ins/Temporal/Duration/prototype/total/relativeto-propertybag-calendar-wrong-type': [FAIL], 'built-ins/Temporal/Duration/prototype/total/relativeto-wrong-type': [FAIL], 'built-ins/Temporal/Duration/prototype/total/timezone-wrong-type': [FAIL], - 'built-ins/Temporal/Instant/compare/argument-object-tostring': [FAIL], 'built-ins/Temporal/Instant/compare/argument-wrong-type': [FAIL], - 'built-ins/Temporal/Instant/compare/instant-string-sub-minute-offset': [FAIL], 'built-ins/Temporal/Instant/from/argument-wrong-type': [FAIL], - 'built-ins/Temporal/Instant/prototype/equals/argument-object-tostring': [FAIL], - 'built-ins/Temporal/Instant/prototype/equals/instant-string-sub-minute-offset': [FAIL], 'built-ins/Temporal/Instant/prototype/since/argument-object-tostring': [FAIL], 'built-ins/Temporal/Instant/prototype/since/argument-wrong-type': [FAIL], 'built-ins/Temporal/Instant/prototype/since/instant-string-sub-minute-offset': [FAIL],