Parcourir la source

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
Linus Groh il y a 3 ans
Parent
commit
31283b5e64

+ 22 - 12
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<TimeZone*> 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<TimeZone>(global_object, *new_target, &GlobalObject::temporal_time_zone_prototype, identifier));
+    auto* object = TRY(ordinary_create_from_constructor<TimeZone>(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;

+ 4 - 2
Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
+ * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
  *
  * 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<OffsetType> 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:

+ 8 - 17
Userland/Libraries/LibJS/Runtime/Temporal/TimeZoneConstructor.cpp

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
+ * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -50,30 +50,21 @@ ThrowCompletionOr<Object*> 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<RangeError>(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