diff --git a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h index 35e166c18b..e6094a7e5f 100644 --- a/Userland/Libraries/LibJS/Runtime/ErrorTypes.h +++ b/Userland/Libraries/LibJS/Runtime/ErrorTypes.h @@ -224,9 +224,11 @@ M(TemporalInvalidPlainTime, "Invalid plain time") \ M(TemporalInvalidPlainTimeLikeObject, "Invalid plain time-like object") \ M(TemporalInvalidPlainYearMonth, "Invalid plain year month") \ + M(TemporalInvalidRelativeToString, "Invalid relative to string '{}'") \ M(TemporalInvalidTime, "Invalid time") \ M(TemporalInvalidTimeString, "Invalid time string '{}'") \ M(TemporalInvalidTimeZoneName, "Invalid time zone name") \ + M(TemporalInvalidTimeZoneString, "Invalid time zone string '{}'") \ M(TemporalInvalidUnitRange, "Invalid unit range, {} is larger than {}") \ M(TemporalInvalidYearMonthString, "Invalid year month string '{}'") \ M(TemporalInvalidZonedDateTimeOffset, "Invalid offset for the provided date and time in the current time zone") \ diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp index f64442255d..fe0a56ab34 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/AbstractOperations.cpp @@ -1325,27 +1325,31 @@ ThrowCompletionOr parse_temporal_month_day_string(GlobalObject } // 13.42 ParseTemporalRelativeToString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalrelativetostring -ThrowCompletionOr parse_temporal_relative_to_string(GlobalObject& global_object, [[maybe_unused]] String const& iso_string) +ThrowCompletionOr parse_temporal_relative_to_string(GlobalObject& global_object, String const& iso_string) { + auto& vm = global_object.vm(); + // 1. Assert: Type(isoString) is String. // 2. If isoString does not satisfy the syntax of a TemporalRelativeToString (see 13.33), then - // a. Throw a RangeError exception. - // TODO + auto parse_result = parse_iso8601(Production::TemporalRelativeToString, iso_string); + if (!parse_result.has_value()) { + // a. Throw a RangeError exception. + return vm.throw_completion(global_object, ErrorType::TemporalInvalidRelativeToString, iso_string); + } // 3. Let result be ! ParseISODateTime(isoString). - auto result = MUST(parse_iso_date_time(global_object, {})); + auto result = MUST(parse_iso_date_time(global_object, *parse_result)); bool z; Optional offset; Optional time_zone; // 4. If isoString satisfies the syntax of a TemporalZonedDateTimeString (see 13.33), then - auto parse_result = parse_iso8601(Production::TemporalZonedDateTimeString, iso_string); + parse_result = parse_iso8601(Production::TemporalZonedDateTimeString, iso_string); if (parse_result.has_value()) { // a. Let timeZoneResult be ! ParseTemporalTimeZoneString(isoString). - // TODO: TRY() instead of MUST() as parse_temporal_time_zone_string() still throws more than it parses :^) - auto time_zone_result = TRY(parse_temporal_time_zone_string(global_object, iso_string)); + auto time_zone_result = MUST(parse_temporal_time_zone_string(global_object, iso_string)); // b. Let z be timeZoneResult.[[Z]]. z = time_zone_result.z; @@ -1391,23 +1395,27 @@ ThrowCompletionOr parse_temporal_time_string(GlobalObject& global_ } // 13.44 ParseTemporalTimeZoneString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaltimezonestring -ThrowCompletionOr parse_temporal_time_zone_string(GlobalObject& global_object, [[maybe_unused]] String const& iso_string) +ThrowCompletionOr parse_temporal_time_zone_string(GlobalObject& global_object, String const& iso_string) { auto& vm = global_object.vm(); // 1. Assert: Type(isoString) is String. // 2. If isoString does not satisfy the syntax of a TemporalTimeZoneString (see 13.33), then - // a. Throw a RangeError exception. + auto parse_result = parse_iso8601(Production::TemporalTimeZoneString, iso_string); + if (!parse_result.has_value()) { + // a. Throw a RangeError exception. + return vm.throw_completion(global_object, ErrorType::TemporalInvalidTimeZoneString, iso_string); + } + // 3. Let z, sign, hours, minutes, seconds, fraction and name be the parts of isoString produced respectively by the UTCDesignator, TimeZoneUTCOffsetSign, TimeZoneUTCOffsetHour, TimeZoneUTCOffsetMinute, TimeZoneUTCOffsetSecond, TimeZoneUTCOffsetFractionalPart, and TimeZoneIANAName productions, or undefined if not present. - Optional z_part; - Optional sign_part; - Optional hours_part; - Optional minutes_part; - Optional seconds_part; - Optional fraction_part; - Optional name_part; - return vm.throw_completion(global_object, ErrorType::NotImplemented, "ParseTemporalTimeZoneString"); + auto z_part = parse_result->utc_designator; + auto sign_part = parse_result->time_zone_utc_offset_sign; + auto hours_part = parse_result->time_zone_utc_offset_hour; + auto minutes_part = parse_result->time_zone_utc_offset_minute; + auto seconds_part = parse_result->time_zone_utc_offset_second; + auto fraction_part = parse_result->time_zone_utc_offset_fractional_part; + auto name_part = parse_result->time_zone_iana_name; // 4. If z is not undefined, then if (z_part.has_value()) { @@ -1427,7 +1435,7 @@ ThrowCompletionOr parse_temporal_time_zone_string(GlobalObject VERIFY(sign_part.has_value()); // b. Set hours to ! ToIntegerOrInfinity(hours). - u8 hours = MUST(Value(js_string(vm, *hours_part)).to_integer_or_infinity(global_object)); + u8 hours = *hours_part->to_uint(); u8 sign; // c. If sign is the code unit 0x002D (HYPHEN-MINUS) or the code unit 0x2212 (MINUS SIGN), then @@ -1442,10 +1450,10 @@ ThrowCompletionOr parse_temporal_time_zone_string(GlobalObject } // e. Set minutes to ! ToIntegerOrInfinity(minutes). - u8 minutes = MUST(Value(js_string(vm, minutes_part.value_or(""sv))).to_integer_or_infinity(global_object)); + u8 minutes = *minutes_part.value_or("0"sv).to_uint(); // f. Set seconds to ! ToIntegerOrInfinity(seconds). - u8 seconds = MUST(Value(js_string(vm, seconds_part.value_or(""sv))).to_integer_or_infinity(global_object)); + u8 seconds = *seconds_part.value_or("0"sv).to_uint(); i32 nanoseconds; // g. If fraction is not undefined, then @@ -1454,7 +1462,7 @@ ThrowCompletionOr parse_temporal_time_zone_string(GlobalObject auto fraction = String::formatted("{}000000000", *fraction_part); // ii. Let nanoseconds be the String value equal to the substring of fraction from 1 to 10. // iii. Set nanoseconds to ! ToIntegerOrInfinity(nanoseconds). - nanoseconds = MUST(Value(js_string(vm, fraction.substring(1, 10))).to_integer_or_infinity(global_object)); + nanoseconds = *fraction.substring(1, 10).to_int(); } // h. Else, else { diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp index 75300b083e..4efc2e0e74 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp @@ -132,6 +132,21 @@ bool ISO8601Parser::parse_date_time_separator() || m_state.lexer.consume_specific('t'); } +// https://tc39.es/proposal-temporal/#prod-UTCDesignator +bool ISO8601Parser::parse_utc_designator() +{ + // UTCDesignator : one of + // Z z + StateTransaction transaction { *this }; + auto success = m_state.lexer.consume_specific('Z') + || m_state.lexer.consume_specific('z'); + if (!success) + return false; + m_state.parse_result.utc_designator = transaction.parsed_string_view(); + transaction.commit(); + return true; +} + // https://tc39.es/proposal-temporal/#prod-DateYear bool ISO8601Parser::parse_date_year() { @@ -354,12 +369,235 @@ bool ISO8601Parser::parse_time_fraction() return parse_fraction(); } +// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetSign +bool ISO8601Parser::parse_time_zone_utc_offset_sign() +{ + // TimeZoneUTCOffsetSign : + // Sign + StateTransaction transaction { *this }; + if (!parse_sign()) + return false; + m_state.parse_result.time_zone_utc_offset_sign = transaction.parsed_string_view(); + transaction.commit(); + return true; +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetHour +bool ISO8601Parser::parse_time_zone_utc_offset_hour() +{ + // TimeZoneUTCOffsetHour : + // Hour + StateTransaction transaction { *this }; + if (!parse_hour()) + return false; + m_state.parse_result.time_zone_utc_offset_hour = transaction.parsed_string_view(); + transaction.commit(); + return true; +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetMinute +bool ISO8601Parser::parse_time_zone_utc_offset_minute() +{ + // TimeZoneUTCOffsetMinute : + // MinuteSecond + StateTransaction transaction { *this }; + if (!parse_minute_second()) + return false; + m_state.parse_result.time_zone_utc_offset_minute = transaction.parsed_string_view(); + transaction.commit(); + return true; +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetSecond +bool ISO8601Parser::parse_time_zone_utc_offset_second() +{ + // TimeZoneUTCOffsetSecond : + // MinuteSecond + StateTransaction transaction { *this }; + if (!parse_minute_second()) + return false; + m_state.parse_result.time_zone_utc_offset_second = transaction.parsed_string_view(); + transaction.commit(); + return true; +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetFractionalPart +bool ISO8601Parser::parse_time_zone_utc_offset_fractional_part() +{ + // TimeZoneUTCOffsetFractionalPart : + // FractionalPart + StateTransaction transaction { *this }; + if (!parse_fractional_part()) + return false; + m_state.parse_result.time_zone_utc_offset_fractional_part = transaction.parsed_string_view(); + transaction.commit(); + return true; +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetFraction +bool ISO8601Parser::parse_time_zone_utc_offset_fraction() +{ + // TimeZoneUTCOffsetFraction : + // DecimalSeparator TimeZoneUTCOffsetFractionalPart + StateTransaction transaction { *this }; + if (!parse_decimal_separator()) + return false; + if (!parse_time_zone_utc_offset_fractional_part()) + return false; + transaction.commit(); + return true; +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneNumericUTCOffset +bool ISO8601Parser::parse_time_zone_numeric_utc_offset() +{ + // TimeZoneNumericUTCOffset : + // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour + // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour : TimeZoneUTCOffsetMinute + // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute + // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour : TimeZoneUTCOffsetMinute : TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction[opt] + // TimeZoneUTCOffsetSign TimeZoneUTCOffsetHour TimeZoneUTCOffsetMinute TimeZoneUTCOffsetSecond TimeZoneUTCOffsetFraction[opt] + StateTransaction transaction { *this }; + if (!parse_time_zone_utc_offset_sign()) + return false; + if (!parse_time_zone_utc_offset_hour()) + return false; + if (m_state.lexer.consume_specific(':')) { + if (!parse_time_zone_utc_offset_minute()) + return false; + if (m_state.lexer.consume_specific(':')) { + if (!parse_time_zone_utc_offset_second()) + return false; + (void)parse_time_zone_utc_offset_fraction(); + } + } else if (parse_time_zone_utc_offset_minute()) { + if (parse_time_zone_utc_offset_second()) + (void)parse_time_zone_utc_offset_fraction(); + } + transaction.commit(); + return true; +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffset +bool ISO8601Parser::parse_time_zone_utc_offset() +{ + // TimeZoneUTCOffset : + // TimeZoneNumericUTCOffset + // UTCDesignator + return parse_time_zone_numeric_utc_offset() + || parse_utc_designator(); +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneUTCOffsetName +bool ISO8601Parser::parse_time_zone_utc_offset_name() +{ + // TimeZoneUTCOffsetName : + // Sign Hour + // Sign Hour : MinuteSecond + // Sign Hour MinuteSecond + // Sign Hour : MinuteSecond : MinuteSecond Fraction[opt] + // Sign Hour MinuteSecond MinuteSecond Fraction[opt] + StateTransaction transaction { *this }; + if (!parse_sign()) + return false; + if (!parse_hour()) + return false; + if (m_state.lexer.consume_specific(':')) { + if (!parse_minute_second()) + return false; + if (m_state.lexer.consume_specific(':')) { + if (!parse_minute_second()) + return false; + (void)parse_fraction(); + } + } else if (parse_minute_second()) { + if (parse_minute_second()) + (void)parse_fraction(); + } + transaction.commit(); + return true; +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneIANAName +bool ISO8601Parser::parse_time_zone_iana_name() +{ + // TZLeadingChar : + // Alpha + // . + // _ + // TZChar : + // Alpha + // . + // - + // _ + // TimeZoneIANANameComponent : + // TZLeadingChar TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] TZChar[opt] but not one of . or .. + // TimeZoneIANANameTail : + // TimeZoneIANANameComponent + // TimeZoneIANANameComponent / TimeZoneIANANameTail + // TimeZoneIANAName : + // TimeZoneIANANameTail + StateTransaction transaction { *this }; + // TODO: Implement the full production. Currently, anything other than "UTC" would get rejected as unknown anyway. + auto success = (m_state.lexer.consume_specific('U') || m_state.lexer.consume_specific('u')) + && (m_state.lexer.consume_specific('T') || m_state.lexer.consume_specific('t')) + && (m_state.lexer.consume_specific('C') || m_state.lexer.consume_specific('c')); + if (!success) + return false; + m_state.parse_result.time_zone_iana_name = transaction.parsed_string_view(); + transaction.commit(); + return true; +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneBracketedName +bool ISO8601Parser::parse_time_zone_bracketed_name() +{ + // TimeZoneBracketedName : + // TimeZoneIANAName + // Etc/GMT ASCIISign Hour + // TimeZoneUTCOffsetName + StateTransaction transaction { *this }; + if (parse_time_zone_iana_name()) { + // no-op. + } else if (m_state.lexer.consume_specific("Etc/GMT"sv)) { + if (!parse_ascii_sign()) + return false; + if (!parse_hour()) + return false; + } else if (!parse_time_zone_utc_offset_name()) { + return false; + } + transaction.commit(); + return true; +} + +// https://tc39.es/proposal-temporal/#prod-TimeZoneBracketedAnnotation +bool ISO8601Parser::parse_time_zone_bracketed_annotation() +{ + // TimeZoneBracketedAnnotation : + // [ TimeZoneBracketedName ] + StateTransaction transaction { *this }; + if (!m_state.lexer.consume_specific('[')) + return false; + if (!parse_time_zone_bracketed_name()) + return false; + if (!m_state.lexer.consume_specific(']')) + return false; + transaction.commit(); + return true; +} + // https://tc39.es/proposal-temporal/#prod-TimeZoneOffsetRequired bool ISO8601Parser::parse_time_zone_offset_required() { // TimeZoneOffsetRequired : // TimeZoneUTCOffset TimeZoneBracketedAnnotation[opt] - return false; + StateTransaction transaction { *this }; + if (!parse_time_zone_utc_offset()) + return false; + (void)parse_time_zone_bracketed_annotation(); + transaction.commit(); + return true; } // https://tc39.es/proposal-temporal/#prod-TimeZoneNameRequired @@ -367,7 +605,12 @@ bool ISO8601Parser::parse_time_zone_name_required() { // TimeZoneNameRequired : // TimeZoneUTCOffset[opt] TimeZoneBracketedAnnotation - return false; + StateTransaction transaction { *this }; + (void)parse_time_zone_utc_offset(); + if (!parse_time_zone_bracketed_annotation()) + return false; + transaction.commit(); + return true; } // https://tc39.es/proposal-temporal/#prod-TimeZone @@ -543,6 +786,35 @@ bool ISO8601Parser::parse_temporal_time_string() || parse_time(); } +// https://tc39.es/proposal-temporal/#prod-TemporalTimeZoneIdentifier +bool ISO8601Parser::parse_temporal_time_zone_identifier() +{ + // TemporalTimeZoneIdentifier : + // TimeZoneNumericUTCOffset + // TimeZoneIANAName + return parse_time_zone_numeric_utc_offset() + || parse_time_zone_iana_name(); +} + +// https://tc39.es/proposal-temporal/#prod-TemporalTimeZoneString +bool ISO8601Parser::parse_temporal_time_zone_string() +{ + // TemporalTimeZoneString : + // TemporalTimeZoneIdentifier + // Date TimeSpecSeparator[opt] TimeZone Calendar[opt] + StateTransaction transaction { *this }; + if (!parse_temporal_time_zone_identifier()) { + if (!parse_date()) + return false; + (void)parse_time_spec_separator(); + if (!parse_time_zone()) + return false; + (void)parse_calendar(); + } + transaction.commit(); + return true; +} + // https://tc39.es/proposal-temporal/#prod-TemporalYearMonthString bool ISO8601Parser::parse_temporal_year_month_string() { @@ -571,15 +843,27 @@ bool ISO8601Parser::parse_temporal_zoned_date_time_string() return true; } +// https://tc39.es/proposal-temporal/#prod-TemporalRelativeToString +bool ISO8601Parser::parse_temporal_relative_to_string() +{ + // TemporalRelativeToString : + // TemporalDateTimeString + // TemporalZonedDateTimeString + return parse_temporal_date_time_string() + || parse_temporal_zoned_date_time_string(); } -#define JS_ENUMERATE_ISO8601_PRODUCTION_PARSERS \ - __JS_ENUMERATE(TemporalDateString, parse_temporal_date_string) \ - __JS_ENUMERATE(TemporalDateTimeString, parse_temporal_date_time_string) \ - __JS_ENUMERATE(TemporalMonthDayString, parse_temporal_month_day_string) \ - __JS_ENUMERATE(TemporalTimeString, parse_temporal_time_string) \ - __JS_ENUMERATE(TemporalYearMonthString, parse_temporal_year_month_string) \ - __JS_ENUMERATE(TemporalZonedDateTimeString, parse_temporal_zoned_date_time_string) +} + +#define JS_ENUMERATE_ISO8601_PRODUCTION_PARSERS \ + __JS_ENUMERATE(TemporalDateString, parse_temporal_date_string) \ + __JS_ENUMERATE(TemporalDateTimeString, parse_temporal_date_time_string) \ + __JS_ENUMERATE(TemporalMonthDayString, parse_temporal_month_day_string) \ + __JS_ENUMERATE(TemporalTimeString, parse_temporal_time_string) \ + __JS_ENUMERATE(TemporalTimeZoneString, parse_temporal_time_zone_string) \ + __JS_ENUMERATE(TemporalYearMonthString, parse_temporal_year_month_string) \ + __JS_ENUMERATE(TemporalZonedDateTimeString, parse_temporal_zoned_date_time_string) \ + __JS_ENUMERATE(TemporalRelativeToString, parse_temporal_relative_to_string) Optional parse_iso8601(Production production, StringView input) { @@ -603,5 +887,4 @@ Optional parse_iso8601(Production production, StringView input) return parser.parse_result(); } - } diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.h b/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.h index 92a894edec..b584aeaa07 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.h @@ -23,6 +23,13 @@ struct ParseResult { Optional time_second; Optional time_fractional_part; Optional calendar_name; + Optional utc_designator; + Optional time_zone_utc_offset_sign; + Optional time_zone_utc_offset_hour; + Optional time_zone_utc_offset_minute; + Optional time_zone_utc_offset_second; + Optional time_zone_utc_offset_fractional_part; + Optional time_zone_iana_name; }; enum class Production { @@ -30,8 +37,10 @@ enum class Production { TemporalDateTimeString, TemporalMonthDayString, TemporalTimeString, + TemporalTimeZoneString, TemporalYearMonthString, TemporalZonedDateTimeString, + TemporalRelativeToString, }; Optional parse_iso8601(Production, StringView); @@ -60,6 +69,7 @@ public: [[nodiscard]] bool parse_minute_second(); [[nodiscard]] bool parse_decimal_separator(); [[nodiscard]] bool parse_date_time_separator(); + [[nodiscard]] bool parse_utc_designator(); [[nodiscard]] bool parse_date_year(); [[nodiscard]] bool parse_date_month(); [[nodiscard]] bool parse_date_day(); @@ -73,6 +83,18 @@ public: [[nodiscard]] bool parse_time_fractional_part(); [[nodiscard]] bool parse_fraction(); [[nodiscard]] bool parse_time_fraction(); + [[nodiscard]] bool parse_time_zone_utc_offset_sign(); + [[nodiscard]] bool parse_time_zone_utc_offset_hour(); + [[nodiscard]] bool parse_time_zone_utc_offset_minute(); + [[nodiscard]] bool parse_time_zone_utc_offset_second(); + [[nodiscard]] bool parse_time_zone_utc_offset_fractional_part(); + [[nodiscard]] bool parse_time_zone_utc_offset_fraction(); + [[nodiscard]] bool parse_time_zone_numeric_utc_offset(); + [[nodiscard]] bool parse_time_zone_utc_offset(); + [[nodiscard]] bool parse_time_zone_utc_offset_name(); + [[nodiscard]] bool parse_time_zone_iana_name(); + [[nodiscard]] bool parse_time_zone_bracketed_name(); + [[nodiscard]] bool parse_time_zone_bracketed_annotation(); [[nodiscard]] bool parse_time_zone_offset_required(); [[nodiscard]] bool parse_time_zone_name_required(); [[nodiscard]] bool parse_time_zone(); @@ -87,8 +109,11 @@ public: [[nodiscard]] bool parse_temporal_date_time_string(); [[nodiscard]] bool parse_temporal_month_day_string(); [[nodiscard]] bool parse_temporal_time_string(); + [[nodiscard]] bool parse_temporal_time_zone_identifier(); + [[nodiscard]] bool parse_temporal_time_zone_string(); [[nodiscard]] bool parse_temporal_year_month_string(); [[nodiscard]] bool parse_temporal_zoned_date_time_string(); + [[nodiscard]] bool parse_temporal_relative_to_string(); private: struct State { diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTimeISO.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTimeISO.js index 0786e0c8a3..79fee23a76 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTimeISO.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.prototype.toZonedDateTimeISO.js @@ -3,8 +3,7 @@ describe("correct behavior", () => { expect(Temporal.Instant.prototype.toZonedDateTimeISO).toHaveLength(1); }); - // TODO: Un-skip when ParseTemporalTimeZoneString is fully implemented - test.skip("basic functionality", () => { + test("basic functionality", () => { const instant = new Temporal.Instant(1625614921123456789n); const zonedDateTime = instant.toZonedDateTimeISO("UTC"); expect(zonedDateTime.year).toBe(2021); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toZonedDateTime.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toZonedDateTime.js index f6c57d8908..9f3c7a8d8e 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toZonedDateTime.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toZonedDateTime.js @@ -58,8 +58,7 @@ describe("correct behavior", () => { expect(zonedDateTime.timeZone).toBe(timeZone); }); - // TODO: Enable when parse_temporal_time_zone_string() is fully implemented - test.skip("basic functionality - time zone identifier", () => { + test("basic functionality - time zone identifier", () => { // 4. in the spec const plainDate = new Temporal.PlainDate(2021, 7, 6); const zonedDateTime = plainDate.toZonedDateTime("UTC"); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js index 433aa60fb0..5230c153a7 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js @@ -95,8 +95,7 @@ describe("correct behavior", () => { expect(plainDateTime.nanosecond).toBe(999); }); - // Un-skip once ParseISODateTime & ParseTemporalDateString are implemented - test.skip("PlainDateTime string argument", () => { + test("PlainDateTime string argument", () => { const plainDateTime = Temporal.PlainDateTime.from("2021-07-06T23:42:01Z"); expect(plainDateTime.year).toBe(2021); expect(plainDateTime.month).toBe(7); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js index 1abdc8ddb9..99f6ce55fb 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainMonthDay/PlainMonthDay.from.js @@ -41,8 +41,7 @@ describe("correct behavior", () => { expect(plainMonthDay.day).toBe(6); }); - // Un-skip once ParseISODateTime, ToTemporalMonthDay & ParseTemporalMonthDayString are fully implemented - test.skip("from date time string", () => { + test("from date time string", () => { const plainMonthDay = Temporal.PlainMonthDay.from("2021-07-06T23:42:01Z"); expect(plainMonthDay.monthCode).toBe("M07"); expect(plainMonthDay.day).toBe(6); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js index 5aa7e2edad..7f3069c393 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js @@ -37,8 +37,7 @@ describe("correct behavior", () => { expect(createdPlainTime.nanosecond).toBe(0); }); - // Un-skip once ParseISODateTime & ParseTemporalTimeString are implemented - test.skip("PlainTime string argument", () => { + test("PlainTime string argument", () => { const createdPlainTime = Temporal.PlainTime.from("2021-08-27T18:44:11Z"); expect(createdPlainTime.hour).toBe(18); expect(createdPlainTime.minute).toBe(44); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js index 0c612222d3..0ba572a08b 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainYearMonth/PlainYearMonth.from.js @@ -62,8 +62,7 @@ describe("correct behavior", () => { expect(plainYearMonth.monthCode).toBe("M07"); }); - // Un-skip once ParseISODateTime & ParseTemporalYearMonthString are fully implemented - test.skip("from date time string", () => { + test("from date time string", () => { const plainYearMonth = Temporal.PlainYearMonth.from("2021-07-06T23:42:01Z"); expect(plainYearMonth.year).toBe(2021); expect(plainYearMonth.month).toBe(7); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.from.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.from.js index b662e9ce9b..313cd0cdf9 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.from.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.from.js @@ -96,7 +96,7 @@ describe("correct behavior", () => { }); // FIXME: Enable when parse_iso_date_time is implemented. - test.skip("from string", () => { + test("from string", () => { const zonedDateTime = Temporal.ZonedDateTime.from( "2021-11-07T00:20:05.100200300+00:00[UTC][u-ca=iso8601]" ); @@ -106,17 +106,17 @@ describe("correct behavior", () => { expect(zonedDateTime.timeZone.id).toBe("UTC"); expect(zonedDateTime.calendar).toBeInstanceOf(Temporal.Calendar); expect(zonedDateTime.calendar.id).toBe("iso8601"); - expect(createdZoneDateTime.year).toBe(2021); - expect(createdZoneDateTime.month).toBe(11); - expect(createdZoneDateTime.day).toBe(7); - expect(createdZoneDateTime.hour).toBe(0); - expect(createdZoneDateTime.minute).toBe(20); - expect(createdZoneDateTime.second).toBe(5); - expect(createdZoneDateTime.millisecond).toBe(100); - expect(createdZoneDateTime.microsecond).toBe(200); - expect(createdZoneDateTime.nanosecond).toBe(300); - expect(createdZoneDateTime.offset).toBe("+00:00"); - expect(createdZoneDateTime.offsetNanoseconds).toBe(0); + expect(zonedDateTime.year).toBe(2021); + expect(zonedDateTime.month).toBe(11); + expect(zonedDateTime.day).toBe(7); + expect(zonedDateTime.hour).toBe(0); + expect(zonedDateTime.minute).toBe(20); + expect(zonedDateTime.second).toBe(5); + expect(zonedDateTime.millisecond).toBe(100); + expect(zonedDateTime.microsecond).toBe(200); + expect(zonedDateTime.nanosecond).toBe(300); + expect(zonedDateTime.offset).toBe("+00:00"); + expect(zonedDateTime.offsetNanoseconds).toBe(0); }); }); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withTimeZone.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withTimeZone.js index 9d5276ccbd..7a391bcced 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withTimeZone.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/ZonedDateTime/ZonedDateTime.prototype.withTimeZone.js @@ -13,8 +13,7 @@ describe("correct behavior", () => { expect(withTimeZoneZonedDateTime.timeZone).toBe(timeZone); }); - // FIXME: Enable this when time zone string parsing is implemented. - test.skip("from time zone string", () => { + test("from time zone string", () => { const object = {}; const zonedDateTime = new Temporal.ZonedDateTime(1n, object); expect(zonedDateTime.timeZone).toBe(object); @@ -32,13 +31,11 @@ describe("errors", () => { }).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime"); }); - // FIXME: Enable this when time zone string parsing is implemented. - test.skip("from invalid time zone string", () => { + test("from invalid time zone string", () => { const zonedDateTime = new Temporal.ZonedDateTime(1n, {}); - // FIXME: Use "toThrowWithMessage" once this has an error message. expect(() => { zonedDateTime.withTimeZone("UTCfoobar"); - }).toThrow(RangeError); + }).toThrowWithMessage(RangeError, "Invalid time zone string 'UTCfoobar'"); }); });