Kaynağa Gözat

LibJS+LibUnicode: Align ECMA-402 "sanctioned" terminology with UTS 35

This is an editorial change in the Intl spec. See:
https://github.com/tc39/ecma402/commit/087995c
https://github.com/tc39/ecma402/commit/233d29c

This also adds a missing spec link for the sanctioned units and fixes a
broken spec link for IsSanctionedSingleUnitIdentifier. In LibUnicode,
the NumberFormat generator is updated to use the constexpr helper to
retrieve sanctioned units.
Timothy Flynn 3 yıl önce
ebeveyn
işleme
066352c9aa

+ 3 - 4
Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeNumberFormat.cpp

@@ -26,6 +26,7 @@
 #include <LibCore/DirIterator.h>
 #include <LibCore/DirIterator.h>
 #include <LibCore/File.h>
 #include <LibCore/File.h>
 #include <LibCore/Stream.h>
 #include <LibCore/Stream.h>
+#include <LibJS/Runtime/Intl/AbstractOperations.h>
 #include <LibUnicode/Locale.h>
 #include <LibUnicode/Locale.h>
 #include <LibUnicode/NumberFormat.h>
 #include <LibUnicode/NumberFormat.h>
 #include <math.h>
 #include <math.h>
@@ -631,11 +632,9 @@ static ErrorOr<void> parse_units(String locale_units_path, UnicodeLocaleData& lo
     };
     };
 
 
     auto is_sanctioned_unit = [](StringView unit_name) {
     auto is_sanctioned_unit = [](StringView unit_name) {
-        // This is a copy of the units sanctioned for use within ECMA-402. LibUnicode generally tries to
-        // avoid being directly dependent on ECMA-402, but this rather significantly reduces the amount
+        // LibUnicode generally tries to avoid being directly dependent on ECMA-402, but this rather significantly reduces the amount
         // of data generated here, and ECMA-402 is currently the only consumer of this data.
         // of data generated here, and ECMA-402 is currently the only consumer of this data.
-        // https://tc39.es/ecma402/#table-sanctioned-simple-unit-identifiers
-        constexpr auto sanctioned_units = AK::Array { "acre"sv, "bit"sv, "byte"sv, "celsius"sv, "centimeter"sv, "day"sv, "degree"sv, "fahrenheit"sv, "fluid-ounce"sv, "foot"sv, "gallon"sv, "gigabit"sv, "gigabyte"sv, "gram"sv, "hectare"sv, "hour"sv, "inch"sv, "kilobit"sv, "kilobyte"sv, "kilogram"sv, "kilometer"sv, "liter"sv, "megabit"sv, "megabyte"sv, "meter"sv, "mile"sv, "mile-scandinavian"sv, "milliliter"sv, "millimeter"sv, "millisecond"sv, "minute"sv, "month"sv, "ounce"sv, "percent"sv, "petabyte"sv, "pound"sv, "second"sv, "stone"sv, "terabit"sv, "terabyte"sv, "week"sv, "yard"sv, "year"sv };
+        constexpr auto sanctioned_units = JS::Intl::sanctioned_single_unit_identifiers();
         return find(sanctioned_units.begin(), sanctioned_units.end(), unit_name) != sanctioned_units.end();
         return find(sanctioned_units.begin(), sanctioned_units.end(), unit_name) != sanctioned_units.end();
     };
     };
 
 

+ 18 - 20
Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp

@@ -140,48 +140,46 @@ bool is_well_formed_currency_code(StringView currency)
 // 6.5.1 IsWellFormedUnitIdentifier ( unitIdentifier ), https://tc39.es/ecma402/#sec-iswellformedunitidentifier
 // 6.5.1 IsWellFormedUnitIdentifier ( unitIdentifier ), https://tc39.es/ecma402/#sec-iswellformedunitidentifier
 bool is_well_formed_unit_identifier(StringView unit_identifier)
 bool is_well_formed_unit_identifier(StringView unit_identifier)
 {
 {
-    // 6.5.2 IsSanctionedSimpleUnitIdentifier ( unitIdentifier ), https://tc39.es/ecma402/#sec-iswellformedunitidentifier
-    constexpr auto is_sanctioned_simple_unit_identifier = [](StringView unit_identifier) {
+    // 6.5.2 IsSanctionedSingleUnitIdentifier ( unitIdentifier ), https://tc39.es/ecma402/#sec-issanctionedsingleunitidentifier
+    constexpr auto is_sanctioned_single_unit_identifier = [](StringView unit_identifier) {
         // 1. If unitIdentifier is listed in Table 2 below, return true.
         // 1. If unitIdentifier is listed in Table 2 below, return true.
         // 2. Else, return false.
         // 2. Else, return false.
-        static constexpr auto sanctioned_units = sanctioned_simple_unit_identifiers();
+        static constexpr auto sanctioned_units = sanctioned_single_unit_identifiers();
         return find(sanctioned_units.begin(), sanctioned_units.end(), unit_identifier) != sanctioned_units.end();
         return find(sanctioned_units.begin(), sanctioned_units.end(), unit_identifier) != sanctioned_units.end();
     };
     };
 
 
-    // 1. If the result of IsSanctionedSimpleUnitIdentifier(unitIdentifier) is true, then
-    if (is_sanctioned_simple_unit_identifier(unit_identifier)) {
+    // 1. If ! IsSanctionedSingleUnitIdentifier(unitIdentifier) is true, then
+    if (is_sanctioned_single_unit_identifier(unit_identifier)) {
         // a. Return true.
         // a. Return true.
         return true;
         return true;
     }
     }
 
 
+    // 2. Let i be ! StringIndexOf(unitIdentifier, "-per-", 0).
     auto indices = unit_identifier.find_all("-per-"sv);
     auto indices = unit_identifier.find_all("-per-"sv);
 
 
-    // 2. If the substring "-per-" does not occur exactly once in unitIdentifier, then
+    // 3. If i is -1 or ! StringIndexOf(unitIdentifier, "-per-", i + 1) is not -1, then
     if (indices.size() != 1) {
     if (indices.size() != 1) {
         // a. Return false.
         // a. Return false.
         return false;
         return false;
     }
     }
 
 
-    // 3. Let numerator be the substring of unitIdentifier from the beginning to just before "-per-".
-    auto numerator = unit_identifier.substring_view(0, indices[0]);
+    // 4. Assert: The five-character substring "-per-" occurs exactly once in unitIdentifier, at index i.
+    // NOTE: We skip this because the indices vector being of size 1 already verifies this invariant.
 
 
-    // 4. If the result of IsSanctionedSimpleUnitIdentifier(numerator) is false, then
-    if (!is_sanctioned_simple_unit_identifier(numerator)) {
-        // a. Return false.
-        return false;
-    }
+    // 5. Let numerator be the substring of unitIdentifier from 0 to i.
+    auto numerator = unit_identifier.substring_view(0, indices[0]);
 
 
-    // 5. Let denominator be the substring of unitIdentifier from just after "-per-" to the end.
+    // 6. Let denominator be the substring of unitIdentifier from i + 5.
     auto denominator = unit_identifier.substring_view(indices[0] + 5);
     auto denominator = unit_identifier.substring_view(indices[0] + 5);
 
 
-    // 6. If the result of IsSanctionedSimpleUnitIdentifier(denominator) is false, then
-    if (!is_sanctioned_simple_unit_identifier(denominator)) {
-        // a. Return false.
-        return false;
+    // 7. If ! IsSanctionedSingleUnitIdentifier(numerator) and ! IsSanctionedSingleUnitIdentifier(denominator) are both true, then
+    if (is_sanctioned_single_unit_identifier(numerator) && is_sanctioned_single_unit_identifier(denominator)) {
+        // a. Return true.
+        return true;
     }
     }
 
 
-    // 7. Return true.
-    return true;
+    // 8. Return false.
+    return false;
 }
 }
 
 
 // 9.2.1 CanonicalizeLocaleList ( locales ), https://tc39.es/ecma402/#sec-canonicalizelocalelist
 // 9.2.1 CanonicalizeLocaleList ( locales ), https://tc39.es/ecma402/#sec-canonicalizelocalelist

+ 2 - 1
Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.h

@@ -54,7 +54,8 @@ struct PatternPartition {
     String value;
     String value;
 };
 };
 
 
-constexpr auto sanctioned_simple_unit_identifiers()
+// Table 2: Single units sanctioned for use in ECMAScript, https://tc39.es/ecma402/#table-sanctioned-single-unit-identifiers
+constexpr auto sanctioned_single_unit_identifiers()
 {
 {
     return AK::Array { "acre"sv, "bit"sv, "byte"sv, "celsius"sv, "centimeter"sv, "day"sv, "degree"sv, "fahrenheit"sv, "fluid-ounce"sv, "foot"sv, "gallon"sv, "gigabit"sv, "gigabyte"sv, "gram"sv, "hectare"sv, "hour"sv, "inch"sv, "kilobit"sv, "kilobyte"sv, "kilogram"sv, "kilometer"sv, "liter"sv, "megabit"sv, "megabyte"sv, "meter"sv, "mile"sv, "mile-scandinavian"sv, "milliliter"sv, "millimeter"sv, "millisecond"sv, "minute"sv, "month"sv, "ounce"sv, "percent"sv, "petabyte"sv, "pound"sv, "second"sv, "stone"sv, "terabit"sv, "terabyte"sv, "week"sv, "yard"sv, "year"sv };
     return AK::Array { "acre"sv, "bit"sv, "byte"sv, "celsius"sv, "centimeter"sv, "day"sv, "degree"sv, "fahrenheit"sv, "fluid-ounce"sv, "foot"sv, "gallon"sv, "gigabit"sv, "gigabyte"sv, "gram"sv, "hectare"sv, "hour"sv, "inch"sv, "kilobit"sv, "kilobyte"sv, "kilogram"sv, "kilometer"sv, "liter"sv, "megabit"sv, "megabyte"sv, "meter"sv, "mile"sv, "mile-scandinavian"sv, "milliliter"sv, "millimeter"sv, "millisecond"sv, "minute"sv, "month"sv, "ounce"sv, "percent"sv, "petabyte"sv, "pound"sv, "second"sv, "stone"sv, "terabit"sv, "terabyte"sv, "week"sv, "yard"sv, "year"sv };
 }
 }

+ 1 - 1
Userland/Libraries/LibJS/Runtime/Intl/Intl.cpp

@@ -141,7 +141,7 @@ JS_DEFINE_NATIVE_FUNCTION(Intl::supported_values_of)
     // 7. Else if key is "unit", then
     // 7. Else if key is "unit", then
     else if (key == "unit"sv) {
     else if (key == "unit"sv) {
         // a. Let list be ! AvailableUnits( ).
         // a. Let list be ! AvailableUnits( ).
-        static auto units = sanctioned_simple_unit_identifiers();
+        static auto units = sanctioned_single_unit_identifiers();
         list = units.span();
         list = units.span();
     }
     }
     // 8. Else,
     // 8. Else,