Browse Source

LibJS: Throw RangeError in PrepareTemporalFields for +/-∞

This is a normative change in the Temporal spec.

See: https://github.com/tc39/proposal-temporal/commit/499282a
Linus Groh 3 years ago
parent
commit
ed98c1afc7

+ 2 - 1
Userland/Libraries/LibJS/Runtime/ErrorTypes.h

@@ -173,7 +173,7 @@
     M(StringRepeatCountMustBe, "repeat count must be a {} number")                                                                      \
     M(TemporalAmbiguousMonthOfPlainMonthDay, "Accessing month of PlainMonthDay is ambiguous, use monthCode instead")                    \
     M(TemporalInvalidCalendar, "Invalid calendar")                                                                                      \
-    M(TemporalInvalidCalendarFunctionResult, "Invalid calendar, {}() function returned undefined")                                      \
+    M(TemporalInvalidCalendarFunctionResult, "Invalid calendar, {}() function returned {}")                                             \
     M(TemporalInvalidCalendarIdentifier, "Invalid calendar identifier '{}'")                                                            \
     M(TemporalInvalidDuration, "Invalid duration")                                                                                      \
     M(TemporalInvalidDurationLikeObject, "Invalid duration-like object")                                                                \
@@ -192,6 +192,7 @@
     M(TemporalInvalidTimeZoneName, "Invalid time zone name")                                                                            \
     M(TemporalMissingOptionsObject, "Required options object is missing or undefined")                                                  \
     M(TemporalMissingRequiredProperty, "Required property {} is missing or undefined")                                                  \
+    M(TemporalPropertyMustBeFinite, "Property must not be Infinity")                                                                    \
     M(TemporalPropertyMustBePositiveInteger, "Property must be a positive integer")                                                     \
     M(ThisHasNotBeenInitialized, "|this| has not been initialized")                                                                     \
     M(ThisIsAlreadyInitialized, "|this| is already initialized")                                                                        \

+ 8 - 15
Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp

@@ -872,31 +872,24 @@ Optional<TemporalTimeZone> parse_temporal_time_zone_string(GlobalObject& global_
     return TemporalTimeZone { .z = false, .offset = offset, .name = name };
 }
 
-// 13.46 ToPositiveIntegerOrInfinity ( argument ), https://tc39.es/proposal-temporal/#sec-temporal-topositiveintegerorinfinity
-double to_positive_integer_or_infinity(GlobalObject& global_object, Value argument)
+// 13.46 ToPositiveInteger ( argument ), https://tc39.es/proposal-temporal/#sec-temporal-topositiveinteger
+double to_positive_integer(GlobalObject& global_object, Value argument)
 {
     auto& vm = global_object.vm();
 
-    // 1. Let integer be ? ToIntegerOrInfinity(argument).
-    auto integer = argument.to_integer_or_infinity(global_object);
+    // 1. Let integer be ? ToIntegerThrowOnInfinity(argument).
+    auto integer = to_integer_throw_on_infinity(global_object, argument, ErrorType::TemporalPropertyMustBePositiveInteger);
     if (vm.exception())
         return {};
 
-    // 2. If integer is -∞𝔽, then
-    if (Value(integer).is_negative_infinity()) {
-        // a. Throw a RangeError exception.
-        vm.throw_exception<RangeError>(global_object, ErrorType::TemporalPropertyMustBePositiveInteger);
-        return {};
-    }
-
-    // 3. If integer ≤ 0, then
+    // 2. If integer ≤ 0, then
     if (integer <= 0) {
         // a. Throw a RangeError exception.
         vm.throw_exception<RangeError>(global_object, ErrorType::TemporalPropertyMustBePositiveInteger);
         return {};
     }
 
-    // 4. Return integer.
+    // 3. Return integer.
     return integer;
 }
 
@@ -939,11 +932,11 @@ Object* prepare_temporal_fields(GlobalObject& global_object, Object& fields, Vec
             // 1. Let Conversion represent the abstract operation named by the Conversion value of the same row.
             // 2. Set value to ? Conversion(value).
             if (property.is_one_of("year", "hour", "minute", "second", "millisecond", "microsecond", "nanosecond", "eraYear")) {
-                value = Value(value.to_integer_or_infinity(global_object));
+                value = Value(to_integer_throw_on_infinity(global_object, value, ErrorType::TemporalPropertyMustBeFinite));
                 if (vm.exception())
                     return {};
             } else if (property.is_one_of("month", "day")) {
-                value = Value(to_positive_integer_or_infinity(global_object, value));
+                value = Value(to_positive_integer(global_object, value));
                 if (vm.exception())
                     return {};
             } else if (property.is_one_of("monthCode", "offset", "era")) {

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

@@ -98,7 +98,7 @@ Optional<ISODateTime> parse_temporal_date_time_string(GlobalObject&, String cons
 Optional<TemporalDuration> parse_temporal_duration_string(GlobalObject&, String const& iso_string);
 Optional<TemporalTime> parse_temporal_time_string(GlobalObject&, String const& iso_string);
 Optional<TemporalTimeZone> parse_temporal_time_zone_string(GlobalObject&, String const& iso_string);
-double to_positive_integer_or_infinity(GlobalObject&, Value argument);
+double to_positive_integer(GlobalObject&, Value argument);
 Object* prepare_temporal_fields(GlobalObject&, Object& fields, Vector<String> const& field_names, Vector<StringView> const& required_fields);
 
 // 13.46 ToIntegerThrowOnInfinity ( argument ), https://tc39.es/proposal-temporal/#sec-temporal-tointegerthrowoninfinity

+ 12 - 13
Userland/Libraries/LibJS/Runtime/Temporal/Calendar.cpp

@@ -137,12 +137,12 @@ double calendar_year(GlobalObject& global_object, Object& calendar, Object& date
 
     // 3. If result is undefined, throw a RangeError exception.
     if (result.is_undefined()) {
-        vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.year.as_string());
+        vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.year.as_string(), vm.names.undefined.as_string());
         return {};
     }
 
-    // 4. Return ? ToIntegerOrInfinity(result).
-    return result.to_integer_or_infinity(global_object);
+    // 4. Return ? ToIntegerThrowOnInfinity(result).
+    return to_integer_throw_on_infinity(global_object, result, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.year.as_string(), vm.names.Infinity.as_string());
 }
 
 // 12.1.10 CalendarMonth ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmonth
@@ -158,12 +158,12 @@ double calendar_month(GlobalObject& global_object, Object& calendar, Object& dat
 
     // 3. If result is undefined, throw a RangeError exception.
     if (result.is_undefined()) {
-        vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.month.as_string());
+        vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.month.as_string(), vm.names.undefined.as_string());
         return {};
     }
 
-    // 4. Return ? ToPositiveIntegerOrInfinity(result).
-    return to_positive_integer_or_infinity(global_object, result);
+    // 4. Return ? ToPositiveInteger(result).
+    return to_positive_integer(global_object, result);
 }
 
 // 12.1.11 CalendarMonthCode ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendarmonthcode
@@ -179,7 +179,7 @@ String calendar_month_code(GlobalObject& global_object, Object& calendar, Object
 
     // 3. If result is undefined, throw a RangeError exception.
     if (result.is_undefined()) {
-        vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.monthCode.as_string());
+        vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.monthCode.as_string(), vm.names.undefined.as_string());
         return {};
     }
 
@@ -200,12 +200,12 @@ double calendar_day(GlobalObject& global_object, Object& calendar, Object& date_
 
     // 3. If result is undefined, throw a RangeError exception.
     if (result.is_undefined()) {
-        vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.day.as_string());
+        vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.day.as_string(), vm.names.undefined.as_string());
         return {};
     }
 
-    // 4. Return ? ToPositiveIntegerOrInfinity(result).
-    return to_positive_integer_or_infinity(global_object, result);
+    // 4. Return ? ToPositiveInteger(result).
+    return to_positive_integer(global_object, result);
 }
 
 // 12.1.13 CalendarDayOfWeek ( calendar, dateLike ), https://tc39.es/proposal-temporal/#sec-temporal-calendardayofweek
@@ -324,12 +324,11 @@ Value calendar_era_year(GlobalObject& global_object, Object& calendar, Object& d
     if (vm.exception())
         return {};
 
-    // 3. If result is not undefined, set result to ? ToIntegerOrInfinity(result).
+    // 3. If result is not undefined, set result to ? ToIntegerThrowOnInfinity(result).
     if (!result.is_undefined()) {
-        auto result_number = result.to_integer_or_infinity(global_object);
+        result = Value(to_integer_throw_on_infinity(global_object, result, ErrorType::TemporalInvalidCalendarFunctionResult, vm.names.eraYear.as_string(), "Infinity"sv));
         if (vm.exception())
             return {};
-        result = Value(result_number);
     }
 
     // 4. Return result.

+ 2 - 2
Userland/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp

@@ -351,8 +351,8 @@ Optional<UnregulatedTemporalTime> to_temporal_time_record(GlobalObject& global_o
             return {};
         }
 
-        // d. Set value to ? ToIntegerOrInfinity(value).
-        auto value_number = value.to_integer_or_infinity(global_object);
+        // d. Set value to ? ToIntegerThrowOnInfinity(value).
+        auto value_number = to_integer_throw_on_infinity(global_object, value, ErrorType::TemporalPropertyMustBeFinite);
         if (vm.exception())
             return {};