Browse Source

LibJS: Use TimeZoneMethods in DisambiguatePossibleInstants

This commit partially updates the DisambiguatePossibleInstants AO to use
a time zone methods record in line with the latest spec.
Shannon Booth 1 year ago
parent
commit
cb1c3e5ea5

+ 32 - 29
Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp

@@ -396,28 +396,33 @@ ThrowCompletionOr<NonnullGCPtr<Instant>> builtin_time_zone_get_instant_for(VM& v
     // 1. Assert: dateTime has an [[InitializedTemporalDateTime]] internal slot.
     // 1. Assert: dateTime has an [[InitializedTemporalDateTime]] internal slot.
 
 
     // 2. Let possibleInstants be ? GetPossibleInstantsFor(timeZone, dateTime).
     // 2. Let possibleInstants be ? GetPossibleInstantsFor(timeZone, dateTime).
-    auto time_zone_record = TRY(create_time_zone_methods_record(vm, NonnullGCPtr<Object> { time_zone.as_object() }, { { TimeZoneMethod::GetPossibleInstantsFor } }));
+    auto time_zone_record = TRY(create_time_zone_methods_record(vm, NonnullGCPtr<Object> { time_zone.as_object() }, { { TimeZoneMethod::GetOffsetNanosecondsFor, TimeZoneMethod::GetPossibleInstantsFor } }));
     auto possible_instants = TRY(get_possible_instants_for(vm, time_zone_record, date_time));
     auto possible_instants = TRY(get_possible_instants_for(vm, time_zone_record, date_time));
 
 
     // 3. Return ? DisambiguatePossibleInstants(possibleInstants, timeZone, dateTime, disambiguation).
     // 3. Return ? DisambiguatePossibleInstants(possibleInstants, timeZone, dateTime, disambiguation).
-    return disambiguate_possible_instants(vm, possible_instants, time_zone, date_time, disambiguation);
+    return disambiguate_possible_instants(vm, possible_instants, time_zone_record, date_time, disambiguation);
 }
 }
 
 
 // 11.6.12 DisambiguatePossibleInstants ( possibleInstants, timeZone, dateTime, disambiguation ), https://tc39.es/proposal-temporal/#sec-temporal-disambiguatepossibleinstants
 // 11.6.12 DisambiguatePossibleInstants ( possibleInstants, timeZone, dateTime, disambiguation ), https://tc39.es/proposal-temporal/#sec-temporal-disambiguatepossibleinstants
-ThrowCompletionOr<NonnullGCPtr<Instant>> disambiguate_possible_instants(VM& vm, MarkedVector<NonnullGCPtr<Instant>> const& possible_instants, Value time_zone, PlainDateTime& date_time, StringView disambiguation)
+ThrowCompletionOr<NonnullGCPtr<Instant>> disambiguate_possible_instants(VM& vm, MarkedVector<NonnullGCPtr<Instant>> const& possible_instants, TimeZoneMethods const& time_zone_record, PlainDateTime& date_time, StringView disambiguation)
 {
 {
-    // 1. Assert: dateTime has an [[InitializedTemporalDateTime]] internal slot.
+    // 1. Assert: TimeZoneMethodsRecordHasLookedUp(timeZoneRec, GET-POSSIBLE-INSTANTS-FOR) is true.
+    VERIFY(time_zone_methods_record_has_looked_up(time_zone_record, TimeZoneMethod::GetPossibleInstantsFor));
+
+    // 2. Assert: If possibleInstants is empty, and disambiguation is not "reject", TimeZoneMethodsRecordHasLookedUp(timeZoneRec, GET-OFFSET-NANOSECONDS-FOR) is true.
+    if (possible_instants.is_empty() && disambiguation != "reject"sv)
+        VERIFY(time_zone_methods_record_has_looked_up(time_zone_record, TimeZoneMethod::GetOffsetNanosecondsFor));
 
 
-    // 2. Let n be possibleInstants's length.
+    // 3. Let n be possibleInstants's length.
     auto n = possible_instants.size();
     auto n = possible_instants.size();
 
 
-    // 3. If n = 1, then
+    // 4. If n = 1, then
     if (n == 1) {
     if (n == 1) {
         // a. Return possibleInstants[0].
         // a. Return possibleInstants[0].
         return possible_instants[0];
         return possible_instants[0];
     }
     }
 
 
-    // 4. If n ≠ 0, then
+    // 5. If n ≠ 0, then
     if (n != 0) {
     if (n != 0) {
         // a. If disambiguation is "earlier" or "compatible", then
         // a. If disambiguation is "earlier" or "compatible", then
         if (disambiguation.is_one_of("earlier"sv, "compatible"sv)) {
         if (disambiguation.is_one_of("earlier"sv, "compatible"sv)) {
@@ -438,50 +443,48 @@ ThrowCompletionOr<NonnullGCPtr<Instant>> disambiguate_possible_instants(VM& vm,
         return vm.throw_completion<RangeError>(ErrorType::TemporalDisambiguatePossibleInstantsRejectMoreThanOne);
         return vm.throw_completion<RangeError>(ErrorType::TemporalDisambiguatePossibleInstantsRejectMoreThanOne);
     }
     }
 
 
-    // 5. Assert: n = 0.
+    // 6. Assert: n = 0.
     VERIFY(n == 0);
     VERIFY(n == 0);
 
 
-    // 6. If disambiguation is "reject", then
+    // 7. If disambiguation is "reject", then
     if (disambiguation == "reject"sv) {
     if (disambiguation == "reject"sv) {
         // a. Throw a RangeError exception.
         // a. Throw a RangeError exception.
         return vm.throw_completion<RangeError>(ErrorType::TemporalDisambiguatePossibleInstantsRejectZero);
         return vm.throw_completion<RangeError>(ErrorType::TemporalDisambiguatePossibleInstantsRejectZero);
     }
     }
 
 
-    // 7. Let epochNanoseconds be GetUTCEpochNanoseconds(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]).
+    // 8. Let epochNanoseconds be GetUTCEpochNanoseconds(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]]).
     auto epoch_nanoseconds = get_utc_epoch_nanoseconds(date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond());
     auto epoch_nanoseconds = get_utc_epoch_nanoseconds(date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond());
 
 
-    // 8. Let dayBeforeNs be epochNanoseconds - ℤ(nsPerDay).
+    // 9. Let dayBeforeNs be epochNanoseconds - ℤ(nsPerDay).
     auto day_before_ns = BigInt::create(vm, epoch_nanoseconds.minus(ns_per_day_bigint));
     auto day_before_ns = BigInt::create(vm, epoch_nanoseconds.minus(ns_per_day_bigint));
 
 
-    // 9. If ! IsValidEpochNanoseconds(dayBeforeNs) is false, throw a RangeError exception.
+    // 10. If IsValidEpochNanoseconds(dayBeforeNs) is false, throw a RangeError exception.
     if (!is_valid_epoch_nanoseconds(day_before_ns))
     if (!is_valid_epoch_nanoseconds(day_before_ns))
         return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidEpochNanoseconds);
         return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidEpochNanoseconds);
 
 
-    // 10. Let dayBefore be ! CreateTemporalInstant(dayBeforeNs).
+    // 11. Let dayBefore be ! CreateTemporalInstant(dayBeforeNs).
     auto* day_before = MUST(create_temporal_instant(vm, day_before_ns));
     auto* day_before = MUST(create_temporal_instant(vm, day_before_ns));
 
 
-    // 11. Let dayAfterNs be epochNanoseconds + ℤ(nsPerDay).
+    // 12. Let dayAfterNs be epochNanoseconds + ℤ(nsPerDay).
     auto day_after_ns = BigInt::create(vm, epoch_nanoseconds.plus(ns_per_day_bigint));
     auto day_after_ns = BigInt::create(vm, epoch_nanoseconds.plus(ns_per_day_bigint));
 
 
-    // 12. If ! IsValidEpochNanoseconds(dayAfterNs) is false, throw a RangeError exception.
+    // 13. If IsValidEpochNanoseconds(dayAfterNs) is false, throw a RangeError exception.
     if (!is_valid_epoch_nanoseconds(day_after_ns))
     if (!is_valid_epoch_nanoseconds(day_after_ns))
         return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidEpochNanoseconds);
         return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidEpochNanoseconds);
 
 
-    // 13. Let dayAfter be ! CreateTemporalInstant(dayAfterNs).
+    // 14. Let dayAfter be ! CreateTemporalInstant(dayAfterNs).
     auto* day_after = MUST(create_temporal_instant(vm, day_after_ns));
     auto* day_after = MUST(create_temporal_instant(vm, day_after_ns));
 
 
-    auto time_zone_record = TRY(create_time_zone_methods_record(vm, NonnullGCPtr<Object> { time_zone.as_object() }, { { TimeZoneMethod::GetOffsetNanosecondsFor, TimeZoneMethod::GetPossibleInstantsFor } }));
-
-    // 14. Let offsetBefore be ? GetOffsetNanosecondsFor(timeZone, dayBefore).
+    // 15. Let offsetBefore be ? GetOffsetNanosecondsFor(timeZoneRec, dayBefore).
     auto offset_before = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *day_before));
     auto offset_before = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *day_before));
 
 
-    // 15. Let offsetAfter be ? GetOffsetNanosecondsFor(timeZone, dayAfter).
+    // 16. Let offsetAfter be ? GetOffsetNanosecondsFor(timeZoneRec, dayAfter).
     auto offset_after = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *day_after));
     auto offset_after = TRY(get_offset_nanoseconds_for(vm, time_zone_record, *day_after));
 
 
-    // 16. Let nanoseconds be offsetAfter - offsetBefore.
+    // 17. Let nanoseconds be offsetAfter - offsetBefore.
     auto nanoseconds = offset_after - offset_before;
     auto nanoseconds = offset_after - offset_before;
 
 
-    // 17. If disambiguation is "earlier", then
+    // 18. If disambiguation is "earlier", then
     if (disambiguation == "earlier"sv) {
     if (disambiguation == "earlier"sv) {
         // a. Let earlier be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], 0, 0, 0, 0, 0, 0, 0, 0, 0, -nanoseconds, undefined).
         // a. Let earlier be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], 0, 0, 0, 0, 0, 0, 0, 0, 0, -nanoseconds, undefined).
         auto earlier = TRY(add_date_time(vm, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond(), date_time.calendar(), 0, 0, 0, 0, 0, 0, 0, 0, 0, -nanoseconds, nullptr));
         auto earlier = TRY(add_date_time(vm, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond(), date_time.calendar(), 0, 0, 0, 0, 0, 0, 0, 0, 0, -nanoseconds, nullptr));
@@ -500,26 +503,26 @@ ThrowCompletionOr<NonnullGCPtr<Instant>> disambiguate_possible_instants(VM& vm,
         return possible_instants_[0];
         return possible_instants_[0];
     }
     }
 
 
-    // 18. Assert: disambiguation is "compatible" or "later".
+    // 19. Assert: disambiguation is "compatible" or "later".
     VERIFY(disambiguation.is_one_of("compatible"sv, "later"sv));
     VERIFY(disambiguation.is_one_of("compatible"sv, "later"sv));
 
 
-    // 19. Let later be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], 0, 0, 0, 0, 0, 0, 0, 0, 0, nanoseconds, undefined).
+    // 20. Let later be ? AddDateTime(dateTime.[[ISOYear]], dateTime.[[ISOMonth]], dateTime.[[ISODay]], dateTime.[[ISOHour]], dateTime.[[ISOMinute]], dateTime.[[ISOSecond]], dateTime.[[ISOMillisecond]], dateTime.[[ISOMicrosecond]], dateTime.[[ISONanosecond]], dateTime.[[Calendar]], 0, 0, 0, 0, 0, 0, 0, 0, 0, nanoseconds, undefined).
     auto later = TRY(add_date_time(vm, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond(), date_time.calendar(), 0, 0, 0, 0, 0, 0, 0, 0, 0, nanoseconds, nullptr));
     auto later = TRY(add_date_time(vm, date_time.iso_year(), date_time.iso_month(), date_time.iso_day(), date_time.iso_hour(), date_time.iso_minute(), date_time.iso_second(), date_time.iso_millisecond(), date_time.iso_microsecond(), date_time.iso_nanosecond(), date_time.calendar(), 0, 0, 0, 0, 0, 0, 0, 0, 0, nanoseconds, nullptr));
 
 
-    // 20. Let laterDateTime be ! CreateTemporalDateTime(later.[[Year]], later.[[Month]], later.[[Day]], later.[[Hour]], later.[[Minute]], later.[[Second]], later.[[Millisecond]], later.[[Microsecond]], later.[[Nanosecond]], dateTime.[[Calendar]]).
+    // 21. Let laterDateTime be ! CreateTemporalDateTime(later.[[Year]], later.[[Month]], later.[[Day]], later.[[Hour]], later.[[Minute]], later.[[Second]], later.[[Millisecond]], later.[[Microsecond]], later.[[Nanosecond]], dateTime.[[Calendar]]).
     auto* later_date_time = MUST(create_temporal_date_time(vm, later.year, later.month, later.day, later.hour, later.minute, later.second, later.millisecond, later.microsecond, later.nanosecond, date_time.calendar()));
     auto* later_date_time = MUST(create_temporal_date_time(vm, later.year, later.month, later.day, later.hour, later.minute, later.second, later.millisecond, later.microsecond, later.nanosecond, date_time.calendar()));
 
 
-    // 21. Set possibleInstants to ? GetPossibleInstantsFor(timeZone, laterDateTime).
+    // 22. Set possibleInstants to ? GetPossibleInstantsFor(timeZone, laterDateTime).
     auto possible_instants_ = TRY(get_possible_instants_for(vm, time_zone_record, *later_date_time));
     auto possible_instants_ = TRY(get_possible_instants_for(vm, time_zone_record, *later_date_time));
 
 
-    // 22. Set n to possibleInstants's length.
+    // 23. Set n to possibleInstants's length.
     n = possible_instants_.size();
     n = possible_instants_.size();
 
 
-    // 23. If n = 0, throw a RangeError exception.
+    // 24. If n = 0, throw a RangeError exception.
     if (n == 0)
     if (n == 0)
         return vm.throw_completion<RangeError>(ErrorType::TemporalDisambiguatePossibleInstantsZero);
         return vm.throw_completion<RangeError>(ErrorType::TemporalDisambiguatePossibleInstantsZero);
 
 
-    // 24. Return possibleInstants[n - 1].
+    // 25. Return possibleInstants[n - 1].
     return possible_instants_[n - 1];
     return possible_instants_[n - 1];
 }
 }
 
 

+ 1 - 1
Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h

@@ -50,7 +50,7 @@ ThrowCompletionOr<double> get_offset_nanoseconds_for(VM& vm, TimeZoneMethods con
 ThrowCompletionOr<String> builtin_time_zone_get_offset_string_for(VM&, Value time_zone, Instant&);
 ThrowCompletionOr<String> builtin_time_zone_get_offset_string_for(VM&, Value time_zone, Instant&);
 ThrowCompletionOr<PlainDateTime*> builtin_time_zone_get_plain_date_time_for(VM&, Value time_zone, Instant&, Object& calendar);
 ThrowCompletionOr<PlainDateTime*> builtin_time_zone_get_plain_date_time_for(VM&, Value time_zone, Instant&, Object& calendar);
 ThrowCompletionOr<NonnullGCPtr<Instant>> builtin_time_zone_get_instant_for(VM&, Value time_zone, PlainDateTime&, StringView disambiguation);
 ThrowCompletionOr<NonnullGCPtr<Instant>> builtin_time_zone_get_instant_for(VM&, Value time_zone, PlainDateTime&, StringView disambiguation);
-ThrowCompletionOr<NonnullGCPtr<Instant>> disambiguate_possible_instants(VM&, MarkedVector<NonnullGCPtr<Instant>> const& possible_instants, Value time_zone, PlainDateTime&, StringView disambiguation);
+ThrowCompletionOr<NonnullGCPtr<Instant>> disambiguate_possible_instants(VM&, MarkedVector<NonnullGCPtr<Instant>> const& possible_instants, TimeZoneMethods const&, PlainDateTime&, StringView disambiguation);
 ThrowCompletionOr<MarkedVector<NonnullGCPtr<Instant>>> get_possible_instants_for(VM&, TimeZoneMethods const&, PlainDateTime const&);
 ThrowCompletionOr<MarkedVector<NonnullGCPtr<Instant>>> get_possible_instants_for(VM&, TimeZoneMethods const&, PlainDateTime const&);
 ThrowCompletionOr<bool> time_zone_equals(VM&, Object& one, Object& two);
 ThrowCompletionOr<bool> time_zone_equals(VM&, Object& one, Object& two);
 
 

+ 1 - 1
Userland/Libraries/LibJS/Runtime/Temporal/ZonedDateTime.cpp

@@ -113,7 +113,7 @@ ThrowCompletionOr<BigInt const*> interpret_iso_date_time_offset(VM& vm, i32 year
         return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidZonedDateTimeOffset);
         return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidZonedDateTimeOffset);
 
 
     // 10. Let instant be ? DisambiguatePossibleInstants(possibleInstants, timeZone, dateTime, disambiguation).
     // 10. Let instant be ? DisambiguatePossibleInstants(possibleInstants, timeZone, dateTime, disambiguation).
-    auto instant = TRY(disambiguate_possible_instants(vm, possible_instants, time_zone, *date_time, disambiguation));
+    auto instant = TRY(disambiguate_possible_instants(vm, possible_instants, time_zone_record, *date_time, disambiguation));
 
 
     // 11. Return instant.[[Nanoseconds]].
     // 11. Return instant.[[Nanoseconds]].
     return &instant->nanoseconds();
     return &instant->nanoseconds();