From 31283b5e645f85329d6cd5e6602426758956d9af Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sat, 22 Jan 2022 21:35:08 +0000 Subject: [PATCH] LibJS: Pass valid offset string directly to CreateTemporalTimeZone This is an editorial change in the Temporal spec. See: - https://github.com/tc39/proposal-temporal/commit/75490b9 - https://github.com/tc39/proposal-temporal/commit/8b70e4b --- .../LibJS/Runtime/Temporal/TimeZone.cpp | 34 ++++++++++++------- .../LibJS/Runtime/Temporal/TimeZone.h | 6 ++-- .../Runtime/Temporal/TimeZoneConstructor.cpp | 25 +++++--------- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp index cf0fb23b79..5e1cc9667e 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp @@ -22,9 +22,8 @@ namespace JS::Temporal { // 11 Temporal.TimeZone Objects, https://tc39.es/proposal-temporal/#sec-temporal-timezone-objects -TimeZone::TimeZone(String identifier, Object& prototype) +TimeZone::TimeZone(Object& prototype) : Object(prototype) - , m_identifier(move(identifier)) { } @@ -71,22 +70,33 @@ ThrowCompletionOr create_temporal_time_zone(GlobalObject& global_obje new_target = global_object.temporal_time_zone_constructor(); // 2. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.TimeZone.prototype%", « [[InitializedTemporalTimeZone]], [[Identifier]], [[OffsetNanoseconds]] »). - // 3. Set object.[[Identifier]] to identifier. - auto* object = TRY(ordinary_create_from_constructor(global_object, *new_target, &GlobalObject::temporal_time_zone_prototype, identifier)); + auto* object = TRY(ordinary_create_from_constructor(global_object, *new_target, &GlobalObject::temporal_time_zone_prototype)); + + // 3. Let offsetNanosecondsResult be ParseTimeZoneOffsetString(identifier). + auto offset_nanoseconds_result = parse_time_zone_offset_string(global_object, identifier); + + // 4. If offsetNanosecondsResult is an abrupt completion, then + if (offset_nanoseconds_result.is_throw_completion()) { + global_object.vm().clear_exception(); - // 4. If identifier satisfies the syntax of a TimeZoneNumericUTCOffset (see 13.33), then - if (is_valid_time_zone_numeric_utc_offset_syntax(identifier)) { - // a. Set object.[[OffsetNanoseconds]] to ! ParseTimeZoneOffsetString(identifier). - object->set_offset_nanoseconds(TRY(parse_time_zone_offset_string(global_object, identifier))); - } - // 5. Else, - else { // a. Assert: ! CanonicalizeTimeZoneName(identifier) is identifier. VERIFY(canonicalize_time_zone_name(identifier) == identifier); - // b. Set object.[[OffsetNanoseconds]] to undefined. + // b. Set object.[[Identifier]] to identifier. + object->set_identifier(identifier); + + // c. Set object.[[OffsetNanoseconds]] to undefined. // NOTE: No-op. } + // 5. Else, + else { + // a. Set object.[[Identifier]] to ! FormatTimeZoneOffsetString(identifier). + // TODO: `identifier` is wrong here. See: https://github.com/tc39/proposal-temporal/pull/2010 + object->set_identifier(format_time_zone_offset_string(offset_nanoseconds_result.value())); + + // b. Set object.[[OffsetNanoseconds]] to offsetNanosecondsResult.[[Value]]. + object->set_offset_nanoseconds(offset_nanoseconds_result.value()); + } // 6. Return object. return object; diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h index a3545cd987..cc932facec 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Linus Groh + * Copyright (c) 2021-2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -20,11 +20,13 @@ public: // Needs to store values in the range -8.64 * 10^13 to 8.64 * 10^13 using OffsetType = double; - TimeZone(String identifier, Object& prototype); + explicit TimeZone(Object& prototype); virtual ~TimeZone() override = default; [[nodiscard]] String const& identifier() const { return m_identifier; } [[nodiscard]] Optional const& offset_nanoseconds() const { return m_offset_nanoseconds; } + + void set_identifier(String identifier) { m_identifier = move(identifier); }; void set_offset_nanoseconds(OffsetType offset_nanoseconds) { m_offset_nanoseconds = offset_nanoseconds; }; private: diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp index 1c91f5c158..753985b059 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Linus Groh + * Copyright (c) 2021-2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ @@ -50,30 +50,21 @@ ThrowCompletionOr TimeZoneConstructor::construct(FunctionObject& new_ta // 2. Set identifier to ? ToString(identifier). auto identifier = TRY(vm.argument(0).to_string(global_object)); - String canonical; - - // 3. If identifier satisfies the syntax of a TimeZoneNumericUTCOffset (see 13.33), then - if (is_valid_time_zone_numeric_utc_offset_syntax(identifier)) { - // a. Let offsetNanoseconds be ? ParseTimeZoneOffsetString(identifier). - auto offset_nanoseconds = TRY(parse_time_zone_offset_string(global_object, identifier)); - - // b. Let canonical be ! FormatTimeZoneOffsetString(offsetNanoseconds). - canonical = format_time_zone_offset_string(offset_nanoseconds); - } - // 4. Else, - else { + // 3. Let parseResult be ParseText(! StringToCodePoints(identifier), TimeZoneNumericUTCOffset). + // 4. If parseResult is a List of errors, then + if (!is_valid_time_zone_numeric_utc_offset_syntax(identifier)) { // a. If ! IsValidTimeZoneName(identifier) is false, then if (!is_valid_time_zone_name(identifier)) { // i. Throw a RangeError exception. return vm.throw_completion(global_object, ErrorType::TemporalInvalidTimeZoneName, identifier); } - // b. Let canonical be ! CanonicalizeTimeZoneName(identifier). - canonical = canonicalize_time_zone_name(identifier); + // b. Set identifier to ! CanonicalizeTimeZoneName(identifier). + identifier = canonicalize_time_zone_name(identifier); } - // 5. Return ? CreateTemporalTimeZone(canonical, NewTarget). - return TRY(create_temporal_time_zone(global_object, canonical, &new_target)); + // 5. Return ? CreateTemporalTimeZone(identifier, NewTarget). + return TRY(create_temporal_time_zone(global_object, identifier, &new_target)); } // 11.3.2 Temporal.TimeZone.from ( item ), https://tc39.es/proposal-temporal/#sec-temporal.timezone.from