Browse Source

LibJS: Implement parsing of TemporalDateString

Linus Groh 3 years ago
parent
commit
02e7de2cba

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

@@ -207,6 +207,7 @@
     M(TemporalInvalidCalendarFieldValue, "Invalid calendar field {}, expected a string")                                                \
     M(TemporalInvalidCalendarFieldValue, "Invalid calendar field {}, expected a string")                                                \
     M(TemporalInvalidCalendarFunctionResult, "Invalid calendar, {}() function returned {}")                                             \
     M(TemporalInvalidCalendarFunctionResult, "Invalid calendar, {}() function returned {}")                                             \
     M(TemporalInvalidCalendarIdentifier, "Invalid calendar identifier '{}'")                                                            \
     M(TemporalInvalidCalendarIdentifier, "Invalid calendar identifier '{}'")                                                            \
+    M(TemporalInvalidDateString, "Invalid date string '{}'")                                                                            \
     M(TemporalInvalidDuration, "Invalid duration")                                                                                      \
     M(TemporalInvalidDuration, "Invalid duration")                                                                                      \
     M(TemporalInvalidDurationLikeObject, "Invalid duration-like object")                                                                \
     M(TemporalInvalidDurationLikeObject, "Invalid duration-like object")                                                                \
     M(TemporalInvalidDurationPropertyValueNonIntegral, "Invalid value for duration property '{}': must be an integer, got {}")          \
     M(TemporalInvalidDurationPropertyValueNonIntegral, "Invalid value for duration property '{}': must be an integer, got {}")          \

+ 9 - 4
Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp

@@ -1240,16 +1240,21 @@ ThrowCompletionOr<String> parse_temporal_calendar_string(GlobalObject& global_ob
 }
 }
 
 
 // 13.38 ParseTemporalDateString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaldatestring
 // 13.38 ParseTemporalDateString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaldatestring
-ThrowCompletionOr<TemporalDate> parse_temporal_date_string(GlobalObject& global_object, [[maybe_unused]] String const& iso_string)
+ThrowCompletionOr<TemporalDate> parse_temporal_date_string(GlobalObject& global_object, String const& iso_string)
 {
 {
+    auto& vm = global_object.vm();
+
     // 1. Assert: Type(isoString) is String.
     // 1. Assert: Type(isoString) is String.
 
 
     // 2. If isoString does not satisfy the syntax of a TemporalDateString (see 13.33), then
     // 2. If isoString does not satisfy the syntax of a TemporalDateString (see 13.33), then
-    // a. Throw a RangeError exception.
-    // TODO
+    auto parse_result = parse_iso8601(Production::TemporalDateString, iso_string);
+    if (!parse_result.has_value()) {
+        // a. Throw a RangeError exception.
+        return vm.throw_completion<RangeError>(global_object, ErrorType::TemporalInvalidDateTimeString, iso_string);
+    }
 
 
     // 3. Let result be ? ParseISODateTime(isoString).
     // 3. Let result be ? ParseISODateTime(isoString).
-    auto result = TRY(parse_iso_date_time(global_object, {}));
+    auto result = TRY(parse_iso_date_time(global_object, *parse_result));
 
 
     // 4. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }.
     // 4. Return the Record { [[Year]]: result.[[Year]], [[Month]]: result.[[Month]], [[Day]]: result.[[Day]], [[Calendar]]: result.[[Calendar]] }.
     return TemporalDate { .year = result.year, .month = result.month, .day = result.day, .calendar = move(result.calendar) };
     return TemporalDate { .year = result.year, .month = result.month, .day = result.day, .calendar = move(result.calendar) };

+ 10 - 1
Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp

@@ -459,9 +459,18 @@ bool ISO8601Parser::parse_calendar_date_time()
     return true;
     return true;
 }
 }
 
 
+// https://tc39.es/proposal-temporal/#prod-TemporalDateString
+bool ISO8601Parser::parse_temporal_date_string()
+{
+    // TemporalDateString :
+    //     CalendarDateTime
+    return parse_calendar_date_time();
+}
+
 }
 }
 
 
-#define JS_ENUMERATE_ISO8601_PRODUCTION_PARSERS
+#define JS_ENUMERATE_ISO8601_PRODUCTION_PARSERS \
+    __JS_ENUMERATE(TemporalDateString, parse_temporal_date_string)
 
 
 Optional<ParseResult> parse_iso8601(Production production, StringView input)
 Optional<ParseResult> parse_iso8601(Production production, StringView input)
 {
 {

+ 3 - 0
Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.h

@@ -26,6 +26,8 @@ struct ParseResult {
 };
 };
 
 
 enum class Production {
 enum class Production {
+    TemporalDateString,
+    TemporalDateTimeString,
 };
 };
 
 
 Optional<ParseResult> parse_iso8601(Production, StringView);
 Optional<ParseResult> parse_iso8601(Production, StringView);
@@ -74,6 +76,7 @@ public:
     [[nodiscard]] bool parse_time_spec_separator();
     [[nodiscard]] bool parse_time_spec_separator();
     [[nodiscard]] bool parse_date_time();
     [[nodiscard]] bool parse_date_time();
     [[nodiscard]] bool parse_calendar_date_time();
     [[nodiscard]] bool parse_calendar_date_time();
+    [[nodiscard]] bool parse_temporal_date_string();
 
 
 private:
 private:
     struct State {
     struct State {

+ 1 - 2
Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.from.js

@@ -28,8 +28,7 @@ describe("correct behavior", () => {
         expect(createdPlainDate.day).toBe(26);
         expect(createdPlainDate.day).toBe(26);
     });
     });
 
 
-    // Un-skip once ParseISODateTime & ParseTemporalDateString are implemented
-    test.skip("PlainDate string argument", () => {
+    test("PlainDate string argument", () => {
         const createdPlainDate = Temporal.PlainDate.from("2021-07-26");
         const createdPlainDate = Temporal.PlainDate.from("2021-07-26");
         expect(createdPlainDate.year).toBe(2021);
         expect(createdPlainDate.year).toBe(2021);
         expect(createdPlainDate.month).toBe(7);
         expect(createdPlainDate.month).toBe(7);

+ 1 - 2
Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.since.js

@@ -102,8 +102,7 @@ describe("correct behavior", () => {
         }
         }
     });
     });
 
 
-    // FIXME: Unskip when plain date string parsing is implemented.
-    test.skip("PlainDate string argument", () => {
+    test("PlainDate string argument", () => {
         const dateTwo = new Temporal.PlainDate(2022, 12, 25);
         const dateTwo = new Temporal.PlainDate(2022, 12, 25);
         const sinceDuration = dateTwo.since("2021-11-14");
         const sinceDuration = dateTwo.since("2021-11-14");
 
 

+ 1 - 2
Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.until.js

@@ -97,8 +97,7 @@ describe("correct behavior", () => {
         }
         }
     });
     });
 
 
-    // FIXME: Unskip when plain date string parsing is implemented.
-    test.skip("PlainDate string argument", () => {
+    test("PlainDate string argument", () => {
         const dateOne = new Temporal.PlainDate(2021, 11, 14);
         const dateOne = new Temporal.PlainDate(2021, 11, 14);
         const untilDuration = dateOne.until("2022-12-25");
         const untilDuration = dateOne.until("2022-12-25");
 
 

+ 1 - 2
Userland/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withPlainDate.js

@@ -50,8 +50,7 @@ describe("correct behavior", () => {
         checkExpectedResults(withPlainDateZonedDateTime);
         checkExpectedResults(withPlainDateZonedDateTime);
     });
     });
 
 
-    // FIXME: Enable when time string parsing is implemented.
-    test.skip("from plain date string", () => {
+    test("from plain date string", () => {
         const plainDateTime = new Temporal.PlainDateTime(2021, 11, 4, 21, 16, 56, 100, 200, 300);
         const plainDateTime = new Temporal.PlainDateTime(2021, 11, 4, 21, 16, 56, 100, 200, 300);
         const timeZone = new Temporal.TimeZone("UTC");
         const timeZone = new Temporal.TimeZone("UTC");
         const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
         const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);