| Differences between
and this patch
- a/Source/JavaScriptCore/ChangeLog +41 lines
Lines 1-3 a/Source/JavaScriptCore/ChangeLog_sec1
1
2020-08-02  Yusuke Suzuki  <ysuzuki@apple.com>
2
3
        [JSC] Implement Intl Language Tag Parser
4
        https://bugs.webkit.org/show_bug.cgi?id=215058
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        This patch adds LanguageTagParser which performs isStructurallyValidLanguageTag[1] validation precisely.
9
        The spec strictly defines acceptable format as language-tag and this is not the same to ICU's one and this
10
        is even tested in test262. We should have LanguageTagParser to validate the input.
11
12
        [1]: https://tc39.es/ecma402/#sec-isstructurallyvalidlanguagetag
13
14
        * runtime/IntlLocale.cpp:
15
        (JSC::LocaleIDBuilder::initialize):
16
        (JSC::IntlLocale::initializeLocale):
17
        * runtime/IntlObject.cpp:
18
        (JSC::canonicalizeLocaleList):
19
        (JSC::parseVariantCode):
20
        (JSC::convertToUnicodeSingletonIndex):
21
        (JSC::isUnicodeExtensionAttribute):
22
        (JSC::isUnicodeExtensionKey):
23
        (JSC::isUnicodeExtensionTypeComponent):
24
        (JSC::isUnicodePUExtensionValue):
25
        (JSC::isUnicodeOtherExtensionValue):
26
        (JSC::isUnicodeTKey):
27
        (JSC::isUnicodeTValue):
28
        (JSC::LanguageTagParser::LanguageTagParser):
29
        (JSC::LanguageTagParser::isEOS):
30
        (JSC::LanguageTagParser::next):
31
        (JSC::LanguageTagParser::parseUnicodeLocaleId):
32
        (JSC::LanguageTagParser::parseUnicodeLanguageId):
33
        (JSC::LanguageTagParser::parseUnicodeExtensionAfterPrefix):
34
        (JSC::LanguageTagParser::parseTransformedExtensionAfterPrefix):
35
        (JSC::LanguageTagParser::parseOtherExtensionAfterPrefix):
36
        (JSC::LanguageTagParser::parsePUExtensionAfterPrefix):
37
        (JSC::LanguageTagParser::parseExtensionsAndPUExtensions):
38
        (JSC::isStructurallyValidLanguageTag):
39
        (JSC::isUnicodeLanguageId):
40
        * runtime/IntlObject.h:
41
1
2020-08-02  Yusuke Suzuki  <ysuzuki@apple.com>
42
2020-08-02  Yusuke Suzuki  <ysuzuki@apple.com>
2
43
3
        Unreviewed, fix CLoop build
44
        Unreviewed, fix CLoop build
- a/Source/JavaScriptCore/runtime/IntlLocale.cpp -4 / +7 lines
Lines 68-74 void IntlLocale::visitChildren(JSCell* cell, SlotVisitor& visitor) a/Source/JavaScriptCore/runtime/IntlLocale.cpp_sec1
68
68
69
class LocaleIDBuilder final {
69
class LocaleIDBuilder final {
70
public:
70
public:
71
    bool initialize(const CString&);
71
    bool initialize(const String&);
72
    CString toCanonical();
72
    CString toCanonical();
73
73
74
    void overrideLanguageScriptRegion(StringView language, StringView script, StringView region);
74
    void overrideLanguageScriptRegion(StringView language, StringView script, StringView region);
Lines 78-86 class LocaleIDBuilder final { a/Source/JavaScriptCore/runtime/IntlLocale.cpp_sec2
78
    Vector<char, 32> m_buffer;
78
    Vector<char, 32> m_buffer;
79
};
79
};
80
80
81
bool LocaleIDBuilder::initialize(const CString& tag)
81
bool LocaleIDBuilder::initialize(const String& tag)
82
{
82
{
83
    m_buffer = localeIDBufferForLanguageTag(tag);
83
    if (!isStructurallyValidLanguageTag(tag))
84
        return false;
85
    ASSERT(tag.isAllASCII());
86
    m_buffer = localeIDBufferForLanguageTag(tag.ascii());
84
    return m_buffer.size();
87
    return m_buffer.size();
85
}
88
}
86
89
Lines 216-222 void IntlLocale::initializeLocale(JSGlobalObject* globalObject, const String& ta a/Source/JavaScriptCore/runtime/IntlLocale.cpp_sec3
216
    }
219
    }
217
220
218
    LocaleIDBuilder localeID;
221
    LocaleIDBuilder localeID;
219
    if (!localeID.initialize(tag.utf8())) {
222
    if (!localeID.initialize(tag)) {
220
        throwRangeError(globalObject, scope, "invalid language tag"_s);
223
        throwRangeError(globalObject, scope, "invalid language tag"_s);
221
        return;
224
        return;
222
    }
225
    }
- a/Source/JavaScriptCore/runtime/IntlObject.cpp -43 / +410 lines
Lines 393-399 bool isUnicodeLocaleIdentifierType(StringView string) a/Source/JavaScriptCore/runtime/IntlObject.cpp_sec1
393
    return true;
393
    return true;
394
}
394
}
395
395
396
// https://tc39.es/ecma402/#sec-isstructurallyvalidlanguagetag
397
// https://tc39.es/ecma402/#sec-canonicalizeunicodelocaleid
396
// https://tc39.es/ecma402/#sec-canonicalizeunicodelocaleid
398
static String canonicalizeLanguageTag(const CString& tag)
397
static String canonicalizeLanguageTag(const CString& tag)
399
{
398
{
Lines 454-490 Vector<String> canonicalizeLocaleList(JSGlobalObject* globalObject, JSValue loca a/Source/JavaScriptCore/runtime/IntlObject.cpp_sec2
454
                return { };
453
                return { };
455
            }
454
            }
456
455
457
            Expected<CString, UTF8ConversionError> rawTag;
456
            String tag;
458
            if (kValue.inherits<IntlLocale>(vm))
457
            if (kValue.inherits<IntlLocale>(vm))
459
                rawTag = jsCast<IntlLocale*>(kValue)->toString().tryGetUtf8();
458
                tag = jsCast<IntlLocale*>(kValue)->toString();
460
            else {
459
            else {
461
                JSString* tag = kValue.toString(globalObject);
460
                JSString* string = kValue.toString(globalObject);
462
                RETURN_IF_EXCEPTION(scope, Vector<String>());
461
                RETURN_IF_EXCEPTION(scope, Vector<String>());
463
462
464
                auto tagValue = tag->value(globalObject);
463
                tag = string->value(globalObject);
465
                RETURN_IF_EXCEPTION(scope, Vector<String>());
464
                RETURN_IF_EXCEPTION(scope, Vector<String>());
466
467
                rawTag = tagValue.tryGetUtf8();
468
            }
469
            if (!rawTag) {
470
                if (rawTag.error() == UTF8ConversionError::OutOfMemory)
471
                    throwOutOfMemoryError(globalObject, scope);
472
                return { };
473
            }
465
            }
474
466
475
            String canonicalizedTag = canonicalizeLanguageTag(rawTag.value());
467
            if (isStructurallyValidLanguageTag(tag)) {
476
            if (canonicalizedTag.isNull()) {
468
                ASSERT(tag.isAllASCII());
477
                String errorMessage = tryMakeString("invalid language tag: ", rawTag->data());
469
                String canonicalizedTag = canonicalizeLanguageTag(tag.ascii());
478
                if (UNLIKELY(!errorMessage)) {
470
                if (!canonicalizedTag.isNull()) {
479
                    throwException(globalObject, scope, createOutOfMemoryError(globalObject));
471
                    if (seenSet.add(canonicalizedTag).isNewEntry)
480
                    return { };
472
                        seen.append(canonicalizedTag);
473
                    continue;
481
                }
474
                }
482
                throwException(globalObject, scope, createRangeError(globalObject, errorMessage));
483
                return { };
484
            }
475
            }
485
476
486
            if (seenSet.add(canonicalizedTag).isNewEntry)
477
            String errorMessage = tryMakeString("invalid language tag: ", tag);
487
                seen.append(canonicalizedTag);
478
            if (UNLIKELY(!errorMessage)) {
479
                throwException(globalObject, scope, createOutOfMemoryError(globalObject));
480
                return { };
481
            }
482
            throwException(globalObject, scope, createRangeError(globalObject, errorMessage));
483
            return { };
488
        }
484
        }
489
    }
485
    }
490
486
Lines 843-883 bool isUnicodeVariantSubtag(StringView string) a/Source/JavaScriptCore/runtime/IntlObject.cpp_sec3
843
    return length == 4 && isASCIIDigit(string[0]) && string.substring(1).isAllSpecialCharacters<isASCIIAlphanumeric>();
839
    return length == 4 && isASCIIDigit(string[0]) && string.substring(1).isAllSpecialCharacters<isASCIIAlphanumeric>();
844
}
840
}
845
841
846
// unicode_language_id, but intersection of BCP47 and UTS35.
842
using VariantCode = uint64_t;
847
// unicode_language_id =
843
static VariantCode parseVariantCode(StringView string)
848
//     | unicode_language_subtag (sep unicode_script_subtag)? (sep unicode_region_subtag)? (sep unicode_variant_subtag)* ;
849
// https://github.com/tc39/proposal-intl-displaynames/issues/79
850
bool isUnicodeLanguageId(StringView string)
851
{
844
{
852
    Vector<StringView, 4> subtags;
845
    ASSERT(isUnicodeVariantSubtag(string));
853
    for (auto subtag : string.splitAllowingEmptyEntries('-'))
846
    ASSERT(string.isAllASCII());
854
        subtags.append(subtag);
847
    ASSERT(string.length() <= 8);
848
    ASSERT(string.length() >= 1);
849
    struct Code {
850
        LChar characters[8] { };
851
    };
852
    static_assert(std::is_unsigned_v<LChar>);
853
    static_assert(sizeof(VariantCode) == sizeof(Code));
854
    Code code { };
855
    for (unsigned index = 0; index < string.length(); ++index)
856
        code.characters[index] = string[index];
857
    VariantCode result = bitwise_cast<VariantCode>(code);
858
    ASSERT(!result); // Not possible since some characters exist.
859
    ASSERT(result != static_cast<VariantCode>(-1)); // Not possible since all characters are ASCII (not Latin-1).
860
    return result;
861
}
862
863
static unsigned convertToUnicodeSingletonIndex(UChar singleton)
864
{
865
    ASSERT(isASCIIAlphanumeric(singleton));
866
    singleton = toASCIILower(singleton);
867
    // 0 - 9 => numeric
868
    // 10 - 35 => alpha
869
    if (isASCIIDigit(singleton))
870
        return singleton - '0';
871
    return (singleton - 'a') + 10;
872
}
873
static constexpr unsigned numberOfUnicodeSingletons = 10 + 26; // Digits + Alphabets.
874
875
static bool isUnicodeExtensionAttribute(StringView string)
876
{
877
    auto length = string.length();
878
    if (length >= 3 && length <= 8)
879
        return string.isAllSpecialCharacters<isASCIIAlphanumeric>();
880
    return false;
881
}
882
883
static bool isUnicodeExtensionKey(StringView string)
884
{
885
    return string.length() == 2 && isASCIIAlphanumeric(string[0]) && isASCIIAlpha(string[1]);
886
}
887
888
static bool isUnicodeExtensionTypeComponent(StringView string)
889
{
890
    auto length = string.length();
891
    if (length >= 3 && length <= 8)
892
        return string.isAllSpecialCharacters<isASCIIAlphanumeric>();
893
    return false;
894
}
895
896
static bool isUnicodePUExtensionValue(StringView string)
897
{
898
    auto length = string.length();
899
    if (length >= 1 && length <= 8)
900
        return string.isAllSpecialCharacters<isASCIIAlphanumeric>();
901
    return false;
902
}
903
904
static bool isUnicodeOtherExtensionValue(StringView string)
905
{
906
    auto length = string.length();
907
    if (length >= 2 && length <= 8)
908
        return string.isAllSpecialCharacters<isASCIIAlphanumeric>();
909
    return false;
910
}
911
912
static bool isUnicodeTKey(StringView string)
913
{
914
    return string.length() == 2 && isASCIIAlpha(string[0]) && isASCIIDigit(string[1]);
915
}
916
917
static bool isUnicodeTValue(StringView string)
918
{
919
    auto length = string.length();
920
    if (length >= 3 && length <= 8)
921
        return string.isAllSpecialCharacters<isASCIIAlphanumeric>();
922
    return false;
923
}
924
925
// The IsStructurallyValidLanguageTag abstract operation verifies that the locale argument (which must be a String value)
926
//
927
//     represents a well-formed "Unicode BCP 47 locale identifier" as specified in Unicode Technical Standard 35 section 3.2,
928
//     does not include duplicate variant subtags, and
929
//     does not include duplicate singleton subtags.
930
//
931
//  The abstract operation returns true if locale can be generated from the EBNF grammar in section 3.2 of the Unicode Technical Standard 35,
932
//  starting with unicode_locale_id, and does not contain duplicate variant or singleton subtags (other than as a private use subtag).
933
//  It returns false otherwise. Terminal value characters in the grammar are interpreted as the Unicode equivalents of the ASCII octet values given.
934
//
935
// https://unicode.org/reports/tr35/#Unicode_locale_identifier
936
class LanguageTagParser {
937
public:
938
    LanguageTagParser(StringView tag)
939
        : m_range(tag.splitAllowingEmptyEntries('-'))
940
        , m_cursor(m_range.begin())
941
    {
942
        ASSERT(m_cursor != m_range.end());
943
        m_current = *m_cursor;
944
    }
945
946
    bool parseUnicodeLocaleId();
947
    bool parseUnicodeLanguageId();
948
949
    bool isEOS()
950
    {
951
        return m_cursor == m_range.end();
952
    }
953
954
    bool next()
955
    {
956
        if (isEOS())
957
            return false;
958
959
        ++m_cursor;
960
        if (isEOS()) {
961
            m_current = StringView();
962
            return false;
963
        }
964
        m_current = *m_cursor;
965
        return true;
966
    }
967
968
private:
969
    bool parseExtensionsAndPUExtensions();
970
971
    bool parseUnicodeExtensionAfterPrefix();
972
    bool parseTransformedExtensionAfterPrefix();
973
    bool parseOtherExtensionAfterPrefix();
974
    bool parsePUExtensionAfterPrefix();
975
976
    StringView::SplitResult m_range;
977
    StringView::SplitResult::Iterator m_cursor;
978
    StringView m_current;
979
};
980
981
bool LanguageTagParser::parseUnicodeLocaleId()
982
{
983
    // unicode_locale_id    = unicode_language_id
984
    //                        extensions*
985
    //                        pu_extensions? ;
986
    ASSERT(!isEOS());
987
    if (!parseUnicodeLanguageId())
988
        return false;
989
    if (isEOS())
990
        return true;
991
    if (!parseExtensionsAndPUExtensions())
992
        return false;
993
    return true;
994
}
995
996
bool LanguageTagParser::parseUnicodeLanguageId()
997
{
998
    // unicode_language_id  = unicode_language_subtag (sep unicode_script_subtag)? (sep unicode_region_subtag)? (sep unicode_variant_subtag)* ;
999
    ASSERT(!isEOS());
1000
    if (!isUnicodeLanguageSubtag(m_current))
1001
        return false;
1002
    if (!next())
1003
        return true;
1004
1005
    if (isUnicodeScriptSubtag(m_current)) {
1006
        if (!next())
1007
            return true;
1008
    }
1009
1010
    if (isUnicodeRegionSubtag(m_current)) {
1011
        if (!next())
1012
            return true;
1013
    }
1014
1015
    HashSet<VariantCode> variantCodes;
1016
    while (true) {
1017
        if (!isUnicodeVariantSubtag(m_current))
1018
            return true;
1019
        // https://tc39.es/ecma402/#sec-isstructurallyvalidlanguagetag
1020
        // does not include duplicate variant subtags
1021
        if (!variantCodes.add(parseVariantCode(m_current)).isNewEntry)
1022
            return false;
1023
        if (!next())
1024
            return true;
1025
    }
1026
}
1027
1028
bool LanguageTagParser::parseUnicodeExtensionAfterPrefix()
1029
{
1030
    // ((sep keyword)+ | (sep attribute)+ (sep keyword)*) ;
1031
    //
1032
    // keyword = key (sep type)? ;
1033
    // key = alphanum alpha ;
1034
    // type = alphanum{3,8} (sep alphanum{3,8})* ;
1035
    // attribute = alphanum{3,8} ;
1036
    ASSERT(!isEOS());
1037
    bool isAttributeOrKeyword = false;
1038
    if (isUnicodeExtensionAttribute(m_current)) {
1039
        isAttributeOrKeyword = true;
1040
        while (true) {
1041
            if (!isUnicodeExtensionAttribute(m_current))
1042
                break;
1043
            if (!next())
1044
                return true;
1045
        }
1046
    }
1047
1048
    if (isUnicodeExtensionKey(m_current)) {
1049
        isAttributeOrKeyword = true;
1050
        while (true) {
1051
            if (!isUnicodeExtensionKey(m_current))
1052
                break;
1053
            if (!next())
1054
                return true;
1055
            while (true) {
1056
                if (!isUnicodeExtensionTypeComponent(m_current))
1057
                    break;
1058
                if (!next())
1059
                    return true;
1060
            }
1061
        }
1062
    }
1063
1064
    if (!isAttributeOrKeyword)
1065
        return false;
1066
    return true;
1067
}
1068
1069
bool LanguageTagParser::parseTransformedExtensionAfterPrefix()
1070
{
1071
    // ((sep tlang (sep tfield)*) | (sep tfield)+) ;
1072
    //
1073
    // tlang = unicode_language_subtag (sep unicode_script_subtag)? (sep unicode_region_subtag)? (sep unicode_variant_subtag)* ;
1074
    // tfield = tkey tvalue;
1075
    // tkey = alpha digit ;
1076
    // tvalue = (sep alphanum{3,8})+ ;
1077
    ASSERT(!isEOS());
1078
    bool isTLangOrTField = false;
1079
    if (isUnicodeLanguageSubtag(m_current)) {
1080
        isTLangOrTField = true;
1081
        if (!parseUnicodeLanguageId())
1082
            return false;
1083
        if (isEOS())
1084
            return true;
1085
    }
855
1086
856
    ASSERT(subtags.size() >= 1);
1087
    if (isUnicodeTKey(m_current)) {
857
    unsigned cursor = 0;
1088
        isTLangOrTField = true;
858
    if (!isUnicodeLanguageSubtag(subtags[cursor]))
1089
        while (true) {
1090
            if (!isUnicodeTKey(m_current))
1091
                break;
1092
            if (!next())
1093
                return false;
1094
            if (!isUnicodeTValue(m_current))
1095
                return false;
1096
            if (!next())
1097
                return true;
1098
            while (true) {
1099
                if (!isUnicodeTValue(m_current))
1100
                    break;
1101
                if (!next())
1102
                    return true;
1103
            }
1104
        }
1105
    }
1106
1107
    if (!isTLangOrTField)
859
        return false;
1108
        return false;
860
    ++cursor;
1109
    return true;
1110
}
861
1111
862
    if (cursor == subtags.size())
1112
bool LanguageTagParser::parseOtherExtensionAfterPrefix()
1113
{
1114
    // (sep alphanum{2,8})+ ;
1115
    ASSERT(!isEOS());
1116
    if (!isUnicodeOtherExtensionValue(m_current))
1117
        return false;
1118
    if (!next())
863
        return true;
1119
        return true;
864
    if (isUnicodeScriptSubtag(subtags[cursor]))
865
        ++cursor;
866
1120
867
    if (cursor == subtags.size())
1121
    while (true) {
1122
        if (!isUnicodeOtherExtensionValue(m_current))
1123
            return true;
1124
        if (!next())
1125
            return true;
1126
    }
1127
}
1128
1129
bool LanguageTagParser::parsePUExtensionAfterPrefix()
1130
{
1131
    // (sep alphanum{1,8})+ ;
1132
    ASSERT(!isEOS());
1133
    if (!isUnicodePUExtensionValue(m_current))
1134
        return false;
1135
    if (!next())
868
        return true;
1136
        return true;
869
    if (isUnicodeRegionSubtag(subtags[cursor]))
870
        ++cursor;
871
1137
872
    while (true) {
1138
    while (true) {
873
        if (cursor == subtags.size())
1139
        if (!isUnicodePUExtensionValue(m_current))
1140
            return true;
1141
        if (!next())
874
            return true;
1142
            return true;
875
        if (!isUnicodeVariantSubtag(subtags[cursor]))
1143
    }
1144
}
1145
1146
bool LanguageTagParser::parseExtensionsAndPUExtensions()
1147
{
1148
    // unicode_locale_id    = unicode_language_id
1149
    //                        extensions*
1150
    //                        pu_extensions? ;
1151
    //
1152
    // extensions = unicode_locale_extensions
1153
    //            | transformed_extensions
1154
    //            | other_extensions ;
1155
    //
1156
    // pu_extensions = sep [xX] (sep alphanum{1,8})+ ;
1157
    ASSERT(!isEOS());
1158
    Bitmap<numberOfUnicodeSingletons> singletonsSet { };
1159
    while (true) {
1160
        if (m_current.length() != 1)
1161
            return true;
1162
        UChar prefixCode = m_current[0];
1163
        if (!isASCIIAlphanumeric(prefixCode))
1164
            return true;
1165
1166
        // https://tc39.es/ecma402/#sec-isstructurallyvalidlanguagetag
1167
        // does not include duplicate singleton subtags.
1168
        //
1169
        // https://unicode.org/reports/tr35/#Unicode_locale_identifier
1170
        // As is often the case, the complete syntactic constraints are not easily captured by ABNF,
1171
        // so there is a further condition: There cannot be more than one extension with the same singleton (-a-, …, -t-, -u-, …).
1172
        // Note that the private use extension (-x-) must come after all other extensions.
1173
        if (singletonsSet.get(convertToUnicodeSingletonIndex(prefixCode)))
876
            return false;
1174
            return false;
877
        ++cursor;
1175
        singletonsSet.set(convertToUnicodeSingletonIndex(prefixCode), true);
1176
1177
        switch (prefixCode) {
1178
        case 'u':
1179
        case 'U': {
1180
            // unicode_locale_extensions = sep [uU] ((sep keyword)+ | (sep attribute)+ (sep keyword)*) ;
1181
            if (!next())
1182
                return false;
1183
            if (!parseUnicodeExtensionAfterPrefix())
1184
                return false;
1185
            if (isEOS())
1186
                return true;
1187
            break; // Next extension.
1188
        }
1189
        case 't':
1190
        case 'T': {
1191
            // transformed_extensions = sep [tT] ((sep tlang (sep tfield)*) | (sep tfield)+) ;
1192
            if (!next())
1193
                return false;
1194
            if (!parseTransformedExtensionAfterPrefix())
1195
                return false;
1196
            if (isEOS())
1197
                return true;
1198
            break; // Next extension.
1199
        }
1200
        case 'x':
1201
        case 'X': {
1202
            // pu_extensions = sep [xX] (sep alphanum{1,8})+ ;
1203
            if (!next())
1204
                return false;
1205
            if (!parsePUExtensionAfterPrefix())
1206
                return false;
1207
            return true; // If pu_extensions appear, no extensions can follow after that. This must be the end of unicode_locale_id.
1208
        }
1209
        default: {
1210
            // other_extensions = sep [alphanum-[tTuUxX]] (sep alphanum{2,8})+ ;
1211
            if (!next())
1212
                return false;
1213
            if (!parseOtherExtensionAfterPrefix())
1214
                return false;
1215
            if (isEOS())
1216
                return true;
1217
            break; // Next extension.
1218
        }
1219
        }
878
    }
1220
    }
879
}
1221
}
880
1222
1223
// https://tc39.es/ecma402/#sec-isstructurallyvalidlanguagetag
1224
bool isStructurallyValidLanguageTag(StringView string)
1225
{
1226
    LanguageTagParser parser(string);
1227
    if (!parser.parseUnicodeLocaleId())
1228
        return false;
1229
    if (!parser.isEOS())
1230
        return false;
1231
    return true;
1232
}
1233
1234
// unicode_language_id, but intersection of BCP47 and UTS35.
1235
// unicode_language_id =
1236
//     | unicode_language_subtag (sep unicode_script_subtag)? (sep unicode_region_subtag)? (sep unicode_variant_subtag)* ;
1237
// https://github.com/tc39/proposal-intl-displaynames/issues/79
1238
bool isUnicodeLanguageId(StringView string)
1239
{
1240
    LanguageTagParser parser(string);
1241
    if (!parser.parseUnicodeLanguageId())
1242
        return false;
1243
    if (!parser.isEOS())
1244
        return false;
1245
    return true;
1246
}
1247
881
bool isWellFormedCurrencyCode(StringView currency)
1248
bool isWellFormedCurrencyCode(StringView currency)
882
{
1249
{
883
    return currency.length() == 3 && currency.isAllSpecialCharacters<isASCIIAlpha>();
1250
    return currency.length() == 3 && currency.isAllSpecialCharacters<isASCIIAlpha>();
- a/Source/JavaScriptCore/runtime/IntlObject.h +1 lines
Lines 117-122 bool isUnicodeScriptSubtag(StringView); a/Source/JavaScriptCore/runtime/IntlObject.h_sec1
117
bool isUnicodeRegionSubtag(StringView);
117
bool isUnicodeRegionSubtag(StringView);
118
bool isUnicodeVariantSubtag(StringView);
118
bool isUnicodeVariantSubtag(StringView);
119
bool isUnicodeLanguageId(StringView);
119
bool isUnicodeLanguageId(StringView);
120
bool isStructurallyValidLanguageTag(StringView);
120
121
121
bool isWellFormedCurrencyCode(StringView);
122
bool isWellFormedCurrencyCode(StringView);
122
123
- a/JSTests/ChangeLog +21 lines
Lines 1-3 a/JSTests/ChangeLog_sec1
1
2020-08-02  Yusuke Suzuki  <ysuzuki@apple.com>
2
3
        [JSC] Implement Intl Language Tag Parser
4
        https://bugs.webkit.org/show_bug.cgi?id=215058
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        * stress/intl-collator.js:
9
        * stress/intl-datetimeformat.js:
10
        * stress/intl-language-tag.js: Added.
11
        (shouldThrow):
12
        (shouldNotThrow):
13
        * stress/intl-locale.js:
14
        * stress/intl-numberformat.js:
15
        * stress/intl-object.js:
16
        * stress/intl-pluralrules.js:
17
        * stress/intl-relativetimeformat.js:
18
        * stress/string-toLocaleLowerCase.js:
19
        * stress/string-toLocaleUpperCase.js:
20
        * test262/expectations.yaml:
21
1
2020-07-30  Saam Barati  <sbarati@apple.com>
22
2020-07-30  Saam Barati  <sbarati@apple.com>
2
23
3
        Skip stress/operand-should-fit-in-abstract-heap-encoded-payload-format.js
24
        Skip stress/operand-should-fit-in-abstract-heap-encoded-payload-format.js
- a/JSTests/stress/intl-collator.js -10 / +9 lines
Lines 194-208 function testCollator(collator, possibleOptionDifferences) { a/JSTests/stress/intl-collator.js_sec1
194
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
194
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
195
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
195
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
196
);
196
);
197
// Replaces outdated tags.
198
shouldBe(JSON.stringify(Intl.Collator.supportedLocalesOf('no-bok')), '["nb"]');
199
// Doesn't throw, but ignores private tags.
200
shouldBe(JSON.stringify(Intl.Collator.supportedLocalesOf('x-some-thing')), '[]');
201
// Throws on problems with length, get, or toString.
197
// Throws on problems with length, get, or toString.
202
shouldThrow(() => Intl.Collator.supportedLocalesOf(Object.create(null, { length: { get() { throw Error() } } })), Error);
198
shouldThrow(() => Intl.Collator.supportedLocalesOf(Object.create(null, { length: { get() { throw Error() } } })), Error);
203
shouldThrow(() => Intl.Collator.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw Error() } } })), Error);
199
shouldThrow(() => Intl.Collator.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw Error() } } })), Error);
204
shouldThrow(() => Intl.Collator.supportedLocalesOf([ { toString() { throw Error() } } ]), Error);
200
shouldThrow(() => Intl.Collator.supportedLocalesOf([ { toString() { throw Error() } } ]), Error);
205
// Throws on bad tags.
201
// Throws on bad tags.
202
shouldThrow(() => Intl.Collator.supportedLocalesOf('no-bok'), RangeError);
203
shouldThrow(() => Intl.Collator.supportedLocalesOf('x-some-thing'), RangeError);
206
shouldThrow(() => Intl.Collator.supportedLocalesOf([ 5 ]), TypeError);
204
shouldThrow(() => Intl.Collator.supportedLocalesOf([ 5 ]), TypeError);
207
shouldThrow(() => Intl.Collator.supportedLocalesOf(''), RangeError);
205
shouldThrow(() => Intl.Collator.supportedLocalesOf(''), RangeError);
208
shouldThrow(() => Intl.Collator.supportedLocalesOf('a'), RangeError);
206
shouldThrow(() => Intl.Collator.supportedLocalesOf('a'), RangeError);
Lines 215-220 function testCollator(collator, possibleOptionDifferences) { a/JSTests/stress/intl-collator.js_sec2
215
shouldThrow(() => Intl.Collator.supportedLocalesOf('en-*'), RangeError);
213
shouldThrow(() => Intl.Collator.supportedLocalesOf('en-*'), RangeError);
216
shouldThrow(() => Intl.Collator.supportedLocalesOf('en-'), RangeError);
214
shouldThrow(() => Intl.Collator.supportedLocalesOf('en-'), RangeError);
217
shouldThrow(() => Intl.Collator.supportedLocalesOf('en--US'), RangeError);
215
shouldThrow(() => Intl.Collator.supportedLocalesOf('en--US'), RangeError);
216
shouldThrow(() => Intl.Collator.supportedLocalesOf('i-klingon'), RangeError); // grandfathered tag is not accepted by IsStructurallyValidLanguageTag
217
shouldThrow(() => Intl.Collator.supportedLocalesOf('x-en-US-12345'), RangeError);
218
shouldThrow(() => Intl.Collator.supportedLocalesOf('x-12345-12345-en-US'), RangeError);
219
shouldThrow(() => Intl.Collator.supportedLocalesOf('x-en-US-12345-12345'), RangeError);
220
shouldThrow(() => Intl.Collator.supportedLocalesOf('x-en-u-foo'), RangeError);
221
shouldThrow(() => Intl.Collator.supportedLocalesOf('x-en-u-foo-u-bar'), RangeError);
222
218
// Accepts valid tags
223
// Accepts valid tags
219
var validLanguageTags = [
224
var validLanguageTags = [
220
    'de', // ISO 639 language code
225
    'de', // ISO 639 language code
Lines 226-241 function testCollator(collator, possibleOptionDifferences) { a/JSTests/stress/intl-collator.js_sec3
226
    'cmn-hans-cn', // + ISO 3166-1 country code
231
    'cmn-hans-cn', // + ISO 3166-1 country code
227
    'es-419', // + UN M.49 region code
232
    'es-419', // + UN M.49 region code
228
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
233
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
229
    'i-klingon', // grandfathered tag
230
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
234
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
231
    'enochian-enochian', // language and variant subtags may be the same
235
    'enochian-enochian', // language and variant subtags may be the same
232
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
236
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
233
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
237
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
234
    'x-en-US-12345', // anything goes in private use tags
235
    'x-12345-12345-en-US',
236
    'x-en-US-12345-12345',
237
    'x-en-u-foo',
238
    'x-en-u-foo-u-bar'
239
];
238
];
240
for (var validLanguageTag of validLanguageTags)
239
for (var validLanguageTag of validLanguageTags)
241
    shouldNotThrow(() => Intl.Collator.supportedLocalesOf(validLanguageTag));
240
    shouldNotThrow(() => Intl.Collator.supportedLocalesOf(validLanguageTag));
- a/JSTests/stress/intl-datetimeformat.js -10 / +9 lines
Lines 86-100 function shouldThrow(func, errorType) { a/JSTests/stress/intl-datetimeformat.js_sec1
86
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
86
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
87
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
87
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
88
);
88
);
89
// Replaces outdated tags.
90
shouldBe(JSON.stringify(Intl.DateTimeFormat.supportedLocalesOf('no-bok')), '["nb"]');
91
// Doesn't throw, but ignores private tags.
92
shouldBe(JSON.stringify(Intl.DateTimeFormat.supportedLocalesOf('x-some-thing')), '[]');
93
// Throws on problems with length, get, or toString.
89
// Throws on problems with length, get, or toString.
94
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf(Object.create(null, { length: { get() { throw new Error(); } } })), Error);
90
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf(Object.create(null, { length: { get() { throw new Error(); } } })), Error);
95
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error(); } } })), Error);
91
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error(); } } })), Error);
96
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf([ { toString() { throw new Error(); } } ]), Error);
92
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf([ { toString() { throw new Error(); } } ]), Error);
97
// Throws on bad tags.
93
// Throws on bad tags.
94
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('no-bok'), RangeError);
95
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('x-some-thing'), RangeError);
98
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf([ 5 ]), TypeError);
96
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf([ 5 ]), TypeError);
99
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf(''), RangeError);
97
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf(''), RangeError);
100
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('a'), RangeError);
98
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('a'), RangeError);
Lines 107-112 function shouldThrow(func, errorType) { a/JSTests/stress/intl-datetimeformat.js_sec2
107
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('en-*'), RangeError);
105
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('en-*'), RangeError);
108
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('en-'), RangeError);
106
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('en-'), RangeError);
109
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('en--US'), RangeError);
107
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('en--US'), RangeError);
108
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('i-klingon'), RangeError); // grandfathered tag is not accepted by IsStructurallyValidLanguageTag
109
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('x-en-US-12345'), RangeError);
110
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('x-12345-12345-en-US'), RangeError);
111
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('x-en-US-12345-12345'), RangeError);
112
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('x-en-u-foo'), RangeError);
113
shouldThrow(() => Intl.DateTimeFormat.supportedLocalesOf('x-en-u-foo-u-bar'), RangeError);
114
110
// Accepts valid tags
115
// Accepts valid tags
111
var validLanguageTags = [
116
var validLanguageTags = [
112
    'de', // ISO 639 language code
117
    'de', // ISO 639 language code
Lines 118-133 function shouldThrow(func, errorType) { a/JSTests/stress/intl-datetimeformat.js_sec3
118
    'cmn-hans-cn', // + ISO 3166-1 country code
123
    'cmn-hans-cn', // + ISO 3166-1 country code
119
    'es-419', // + UN M.49 region code
124
    'es-419', // + UN M.49 region code
120
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
125
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
121
    'i-klingon', // grandfathered tag
122
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
126
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
123
    'enochian-enochian', // language and variant subtags may be the same
127
    'enochian-enochian', // language and variant subtags may be the same
124
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
128
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
125
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
129
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
126
    'x-en-US-12345', // anything goes in private use tags
127
    'x-12345-12345-en-US',
128
    'x-en-US-12345-12345',
129
    'x-en-u-foo',
130
    'x-en-u-foo-u-bar'
131
];
130
];
132
for (var validLanguageTag of validLanguageTags)
131
for (var validLanguageTag of validLanguageTags)
133
    shouldNotThrow(() => Intl.DateTimeFormat.supportedLocalesOf(validLanguageTag));
132
    shouldNotThrow(() => Intl.DateTimeFormat.supportedLocalesOf(validLanguageTag));
- a/JSTests/stress/intl-language-tag.js +58 lines
Line 0 a/JSTests/stress/intl-language-tag.js_sec1
1
function shouldThrow(func, errorType) {
2
    let error;
3
    try {
4
        func();
5
    } catch (e) {
6
        error = e;
7
    }
8
9
    if (!(error instanceof errorType))
10
        throw new Error(`Expected ${errorType.name}!`);
11
}
12
13
function shouldNotThrow(func) {
14
    func();
15
}
16
17
shouldThrow(() => Intl.getCanonicalLocales("en-US-u-ca-u-nu"), RangeError);
18
shouldThrow(() => Intl.getCanonicalLocales("en-US-a-ok1-a-ok2"), RangeError);
19
shouldNotThrow(() => Intl.getCanonicalLocales("en-US-a-ok1"));
20
shouldNotThrow(() => Intl.getCanonicalLocales("de"));
21
shouldNotThrow(() => Intl.getCanonicalLocales("fr"));
22
shouldNotThrow(() => Intl.getCanonicalLocales("ja"));
23
shouldThrow(() => Intl.getCanonicalLocales("i-enochian"), RangeError);
24
shouldNotThrow(() => Intl.getCanonicalLocales("zh-Hant"));
25
shouldNotThrow(() => Intl.getCanonicalLocales("zh-Hans"));
26
shouldNotThrow(() => Intl.getCanonicalLocales("sr-Cyrl"));
27
shouldNotThrow(() => Intl.getCanonicalLocales("sr-Latn"));
28
shouldThrow(() => Intl.getCanonicalLocales("zh-cmn-Hans-CN"), RangeError);
29
shouldNotThrow(() => Intl.getCanonicalLocales("cmn-Hans-CN"));
30
shouldThrow(() => Intl.getCanonicalLocales("zh-yue-HK"), RangeError);
31
shouldNotThrow(() => Intl.getCanonicalLocales("yue-HK"));
32
shouldNotThrow(() => Intl.getCanonicalLocales("zh-Hans-CN"));
33
shouldNotThrow(() => Intl.getCanonicalLocales("sr-Latn-RS"));
34
shouldNotThrow(() => Intl.getCanonicalLocales("sl-rozaj"));
35
shouldNotThrow(() => Intl.getCanonicalLocales("sl-rozaj-biske"));
36
shouldThrow(() => Intl.getCanonicalLocales("sl-rozaj-biske-biske"), RangeError);
37
shouldNotThrow(() => Intl.getCanonicalLocales("sl-nedis"));
38
shouldNotThrow(() => Intl.getCanonicalLocales("de-CH-1901"));
39
shouldNotThrow(() => Intl.getCanonicalLocales("sl-IT-nedis"));
40
shouldNotThrow(() => Intl.getCanonicalLocales("hy-Latn-IT-arevela"));
41
shouldNotThrow(() => Intl.getCanonicalLocales("de-DE"));
42
shouldNotThrow(() => Intl.getCanonicalLocales("en-US"));
43
shouldNotThrow(() => Intl.getCanonicalLocales("es-419"));
44
shouldNotThrow(() => Intl.getCanonicalLocales("de-CH-x-phonebk"));
45
shouldNotThrow(() => Intl.getCanonicalLocales("az-Arab-x-AZE-derbend"));
46
shouldThrow(() => Intl.getCanonicalLocales("x-whatever"), RangeError);
47
shouldNotThrow(() => Intl.getCanonicalLocales("qaa-Qaaa-QM-x-southern"));
48
shouldNotThrow(() => Intl.getCanonicalLocales("de-Qaaa"));
49
shouldNotThrow(() => Intl.getCanonicalLocales("sr-Latn-QM"));
50
shouldNotThrow(() => Intl.getCanonicalLocales("sr-Qaaa-RS"));
51
shouldNotThrow(() => Intl.getCanonicalLocales("en-US-u-islamcal"));
52
shouldNotThrow(() => Intl.getCanonicalLocales("zh-CN-a-myext-x-private"));
53
shouldNotThrow(() => Intl.getCanonicalLocales("en-a-myext-b-another"));
54
shouldNotThrow(() => Intl.getCanonicalLocales("en-US-u-nu-fullwide"));
55
shouldThrow(() => Intl.getCanonicalLocales("de-419-DE"), RangeError);
56
shouldThrow(() => Intl.getCanonicalLocales("a-DE"), RangeError);
57
shouldThrow(() => Intl.getCanonicalLocales("ar-a-aaa-b-bbb-a-ccc"), RangeError);
58
shouldThrow(() => Intl.getCanonicalLocales(""), RangeError);
- a/JSTests/stress/intl-locale.js -6 / +6 lines
Lines 45-50 function shouldThrow(func, errorType) { a/JSTests/stress/intl-locale.js_sec1
45
shouldThrow(() => new Intl.Locale({}), RangeError);
45
shouldThrow(() => new Intl.Locale({}), RangeError);
46
shouldThrow(() => new Intl.Locale({ toString() { throw new Error(); } }), Error);
46
shouldThrow(() => new Intl.Locale({ toString() { throw new Error(); } }), Error);
47
shouldThrow(() => new Intl.Locale([]), RangeError);
47
shouldThrow(() => new Intl.Locale([]), RangeError);
48
shouldThrow(() => new Intl.Locale('i-klingon'), RangeError); // grandfathered tag is not accepted by IsStructurallyValidLanguageTag
49
shouldThrow(() => new Intl.Locale('x-en-US-12345'), RangeError);
50
shouldThrow(() => new Intl.Locale('x-12345-12345-en-US'), RangeError);
51
shouldThrow(() => new Intl.Locale('x-en-US-12345-12345'), RangeError);
52
shouldThrow(() => new Intl.Locale('x-en-u-foo'), RangeError);
53
shouldThrow(() => new Intl.Locale('x-en-u-foo-u-bar'), RangeError);
48
shouldNotThrow(() => new Intl.Locale({ toString() { return 'en'; } }));
54
shouldNotThrow(() => new Intl.Locale({ toString() { return 'en'; } }));
49
55
50
shouldThrow(() => new Intl.Locale('en', null), TypeError);
56
shouldThrow(() => new Intl.Locale('en', null), TypeError);
Lines 72-87 function shouldThrow(func, errorType) { a/JSTests/stress/intl-locale.js_sec2
72
    'cmn-hans-cn', // + ISO 3166-1 country code
78
    'cmn-hans-cn', // + ISO 3166-1 country code
73
    'es-419', // + UN M.49 region code
79
    'es-419', // + UN M.49 region code
74
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
80
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
75
    'i-klingon', // grandfathered tag
76
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
81
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
77
    'enochian-enochian', // language and variant subtags may be the same
82
    'enochian-enochian', // language and variant subtags may be the same
78
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
83
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
79
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
84
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
80
    'x-en-US-12345', // anything goes in private use tags
81
    'x-12345-12345-en-US',
82
    'x-en-US-12345-12345',
83
    'x-en-u-foo',
84
    'x-en-u-foo-u-bar'
85
];
85
];
86
for (let validLanguageTag of validLanguageTags)
86
for (let validLanguageTag of validLanguageTags)
87
    shouldNotThrow(() => new Intl.Locale(validLanguageTag));
87
    shouldNotThrow(() => new Intl.Locale(validLanguageTag));
- a/JSTests/stress/intl-numberformat.js -12 / +9 lines
Lines 1-5 a/JSTests/stress/intl-numberformat.js_sec1
1
//@ runBigIntEnabled
2
3
function shouldBe(actual, expected) {
1
function shouldBe(actual, expected) {
4
    if (actual !== expected)
2
    if (actual !== expected)
5
        throw new Error(`expected ${expected} but got ${actual}`);
3
        throw new Error(`expected ${expected} but got ${actual}`);
Lines 226-240 function testNumberFormat(numberFormat, possibleDifferences) { a/JSTests/stress/intl-numberformat.js_sec2
226
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
224
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
227
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
225
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
228
);
226
);
229
// Replaces outdated tags.
230
shouldBe(JSON.stringify(Intl.NumberFormat.supportedLocalesOf('no-bok')), '["nb"]');
231
// Doesn't throw, but ignores private tags.
232
shouldBe(JSON.stringify(Intl.NumberFormat.supportedLocalesOf('x-some-thing')), '[]');
233
// Throws on problems with length, get, or toString.
227
// Throws on problems with length, get, or toString.
234
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf(Object.create(null, { length: { get() { throw new Error(); } } })), Error);
228
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf(Object.create(null, { length: { get() { throw new Error(); } } })), Error);
235
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error(); } } })), Error);
229
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error(); } } })), Error);
236
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf([ { toString() { throw new Error(); } } ]), Error);
230
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf([ { toString() { throw new Error(); } } ]), Error);
237
// Throws on bad tags.
231
// Throws on bad tags.
232
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('no-bok'), RangeError);
233
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('x-some-thing'), RangeError);
238
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf([ 5 ]), TypeError);
234
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf([ 5 ]), TypeError);
239
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf(''), RangeError);
235
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf(''), RangeError);
240
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('a'), RangeError);
236
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('a'), RangeError);
Lines 247-252 function testNumberFormat(numberFormat, possibleDifferences) { a/JSTests/stress/intl-numberformat.js_sec3
247
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('en-*'), RangeError);
243
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('en-*'), RangeError);
248
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('en-'), RangeError);
244
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('en-'), RangeError);
249
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('en--US'), RangeError);
245
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('en--US'), RangeError);
246
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('i-klingon'), RangeError); // grandfathered tag is not accepted by IsStructurallyValidLanguageTag
247
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('x-en-US-12345'), RangeError);
248
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('x-12345-12345-en-US'), RangeError);
249
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('x-en-US-12345-12345'), RangeError);
250
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('x-en-u-foo'), RangeError);
251
shouldThrow(() => Intl.NumberFormat.supportedLocalesOf('x-en-u-foo-u-bar'), RangeError);
252
250
// Accepts valid tags
253
// Accepts valid tags
251
var validLanguageTags = [
254
var validLanguageTags = [
252
    'de', // ISO 639 language code
255
    'de', // ISO 639 language code
Lines 258-273 function testNumberFormat(numberFormat, possibleDifferences) { a/JSTests/stress/intl-numberformat.js_sec4
258
    'cmn-hans-cn', // + ISO 3166-1 country code
261
    'cmn-hans-cn', // + ISO 3166-1 country code
259
    'es-419', // + UN M.49 region code
262
    'es-419', // + UN M.49 region code
260
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
263
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
261
    'i-klingon', // grandfathered tag
262
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
264
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
263
    'enochian-enochian', // language and variant subtags may be the same
265
    'enochian-enochian', // language and variant subtags may be the same
264
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
266
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
265
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
267
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
266
    'x-en-US-12345', // anything goes in private use tags
267
    'x-12345-12345-en-US',
268
    'x-en-US-12345-12345',
269
    'x-en-u-foo',
270
    'x-en-u-foo-u-bar'
271
];
268
];
272
for (var validLanguageTag of validLanguageTags)
269
for (var validLanguageTag of validLanguageTags)
273
    shouldNotThrow(() => Intl.NumberFormat.supportedLocalesOf(validLanguageTag));
270
    shouldNotThrow(() => Intl.NumberFormat.supportedLocalesOf(validLanguageTag));
- a/JSTests/stress/intl-object.js -10 / +9 lines
Lines 74-88 function shouldThrow(func, errorType) { a/JSTests/stress/intl-object.js_sec1
74
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
74
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
75
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
75
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
76
);
76
);
77
// Replaces outdated tags.
78
shouldBe(JSON.stringify(Intl.getCanonicalLocales('no-bok')), '["nb"]');
79
// Canonicalizes private tags.
80
shouldBe(JSON.stringify(Intl.getCanonicalLocales('X-some-thing')), '["x-some-thing"]');
81
// Throws on problems with length, get, or toString.
77
// Throws on problems with length, get, or toString.
82
shouldThrow(() => Intl.getCanonicalLocales(Object.create(null, { length: { get() { throw new Error(); } } })), Error);
78
shouldThrow(() => Intl.getCanonicalLocales(Object.create(null, { length: { get() { throw new Error(); } } })), Error);
83
shouldThrow(() => Intl.getCanonicalLocales(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error(); } } })), Error);
79
shouldThrow(() => Intl.getCanonicalLocales(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error(); } } })), Error);
84
shouldThrow(() => Intl.getCanonicalLocales([ { toString() { throw new Error(); } } ]), Error);
80
shouldThrow(() => Intl.getCanonicalLocales([ { toString() { throw new Error(); } } ]), Error);
85
// Throws on bad tags.
81
// Throws on bad tags.
82
shouldThrow(() => Intl.getCanonicalLocales('no-bok'), RangeError);
83
shouldThrow(() => Intl.getCanonicalLocales('x-some-thing'), RangeError);
86
shouldThrow(() => Intl.getCanonicalLocales([ 5 ]), TypeError);
84
shouldThrow(() => Intl.getCanonicalLocales([ 5 ]), TypeError);
87
shouldThrow(() => Intl.getCanonicalLocales(''), RangeError);
85
shouldThrow(() => Intl.getCanonicalLocales(''), RangeError);
88
shouldThrow(() => Intl.getCanonicalLocales('a'), RangeError);
86
shouldThrow(() => Intl.getCanonicalLocales('a'), RangeError);
Lines 95-100 function shouldThrow(func, errorType) { a/JSTests/stress/intl-object.js_sec2
95
shouldThrow(() => Intl.getCanonicalLocales('en-*'), RangeError);
93
shouldThrow(() => Intl.getCanonicalLocales('en-*'), RangeError);
96
shouldThrow(() => Intl.getCanonicalLocales('en-'), RangeError);
94
shouldThrow(() => Intl.getCanonicalLocales('en-'), RangeError);
97
shouldThrow(() => Intl.getCanonicalLocales('en--US'), RangeError);
95
shouldThrow(() => Intl.getCanonicalLocales('en--US'), RangeError);
96
shouldThrow(() => Intl.getCanonicalLocales('i-klingon'), RangeError); // grandfathered tag is not accepted by IsStructurallyValidLanguageTag
97
shouldThrow(() => Intl.getCanonicalLocales('x-en-US-12345'), RangeError);
98
shouldThrow(() => Intl.getCanonicalLocales('x-12345-12345-en-US'), RangeError);
99
shouldThrow(() => Intl.getCanonicalLocales('x-en-US-12345-12345'), RangeError);
100
shouldThrow(() => Intl.getCanonicalLocales('x-en-u-foo'), RangeError);
101
shouldThrow(() => Intl.getCanonicalLocales('x-en-u-foo-u-bar'), RangeError);
102
98
// Accepts valid tags
103
// Accepts valid tags
99
var validLanguageTags = [
104
var validLanguageTags = [
100
    'de', // ISO 639 language code
105
    'de', // ISO 639 language code
Lines 106-121 function shouldThrow(func, errorType) { a/JSTests/stress/intl-object.js_sec3
106
    'cmn-hans-cn', // + ISO 3166-1 country code
111
    'cmn-hans-cn', // + ISO 3166-1 country code
107
    'es-419', // + UN M.49 region code
112
    'es-419', // + UN M.49 region code
108
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
113
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
109
    'i-klingon', // grandfathered tag
110
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
114
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
111
    'enochian-enochian', // language and variant subtags may be the same
115
    'enochian-enochian', // language and variant subtags may be the same
112
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
116
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
113
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
117
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
114
    'x-en-US-12345', // anything goes in private use tags
115
    'x-12345-12345-en-US',
116
    'x-en-US-12345-12345',
117
    'x-en-u-foo',
118
    'x-en-u-foo-u-bar'
119
];
118
];
120
for (var validLanguageTag of validLanguageTags)
119
for (var validLanguageTag of validLanguageTags)
121
    shouldNotThrow(() => Intl.getCanonicalLocales(validLanguageTag));
120
    shouldNotThrow(() => Intl.getCanonicalLocales(validLanguageTag));
- a/JSTests/stress/intl-pluralrules.js -10 / +9 lines
Lines 85-99 function shouldThrow(func, errorType) { a/JSTests/stress/intl-pluralrules.js_sec1
85
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
85
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
86
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
86
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
87
);
87
);
88
// Replaces outdated tags.
89
shouldBe(JSON.stringify(Intl.PluralRules.supportedLocalesOf('no-bok')), '["nb"]');
90
// Doesn't throw, but ignores private tags.
91
shouldBe(JSON.stringify(Intl.PluralRules.supportedLocalesOf('x-some-thing')), '[]');
92
// Throws on problems with length, get, or toString.
88
// Throws on problems with length, get, or toString.
93
shouldThrow(() => Intl.PluralRules.supportedLocalesOf(Object.create(null, { length: { get() { throw new Error(); } } })), Error);
89
shouldThrow(() => Intl.PluralRules.supportedLocalesOf(Object.create(null, { length: { get() { throw new Error(); } } })), Error);
94
shouldThrow(() => Intl.PluralRules.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error(); } } })), Error);
90
shouldThrow(() => Intl.PluralRules.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error(); } } })), Error);
95
shouldThrow(() => Intl.PluralRules.supportedLocalesOf([ { toString() { throw new Error(); } } ]), Error);
91
shouldThrow(() => Intl.PluralRules.supportedLocalesOf([ { toString() { throw new Error(); } } ]), Error);
96
// Throws on bad tags.
92
// Throws on bad tags.
93
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('no-bok'), RangeError);
94
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('x-some-thing'), RangeError);
97
shouldThrow(() => Intl.PluralRules.supportedLocalesOf([ 5 ]), TypeError);
95
shouldThrow(() => Intl.PluralRules.supportedLocalesOf([ 5 ]), TypeError);
98
shouldThrow(() => Intl.PluralRules.supportedLocalesOf(''), RangeError);
96
shouldThrow(() => Intl.PluralRules.supportedLocalesOf(''), RangeError);
99
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('a'), RangeError);
97
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('a'), RangeError);
Lines 106-111 function shouldThrow(func, errorType) { a/JSTests/stress/intl-pluralrules.js_sec2
106
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('en-*'), RangeError);
104
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('en-*'), RangeError);
107
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('en-'), RangeError);
105
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('en-'), RangeError);
108
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('en--US'), RangeError);
106
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('en--US'), RangeError);
107
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('i-klingon'), RangeError); // grandfathered tag is not accepted by IsStructurallyValidLanguageTag
108
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('x-en-US-12345'), RangeError);
109
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('x-12345-12345-en-US'), RangeError);
110
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('x-en-US-12345-12345'), RangeError);
111
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('x-en-u-foo'), RangeError);
112
shouldThrow(() => Intl.PluralRules.supportedLocalesOf('x-en-u-foo-u-bar'), RangeError);
113
109
// Accepts valid tags
114
// Accepts valid tags
110
var validLanguageTags = [
115
var validLanguageTags = [
111
    'de', // ISO 639 language code
116
    'de', // ISO 639 language code
Lines 117-132 function shouldThrow(func, errorType) { a/JSTests/stress/intl-pluralrules.js_sec3
117
    'cmn-hans-cn', // + ISO 3166-1 country code
122
    'cmn-hans-cn', // + ISO 3166-1 country code
118
    'es-419', // + UN M.49 region code
123
    'es-419', // + UN M.49 region code
119
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
124
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
120
    'i-klingon', // grandfathered tag
121
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
125
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
122
    'enochian-enochian', // language and variant subtags may be the same
126
    'enochian-enochian', // language and variant subtags may be the same
123
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
127
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
124
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
128
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
125
    'x-en-US-12345', // anything goes in private use tags
126
    'x-12345-12345-en-US',
127
    'x-en-US-12345-12345',
128
    'x-en-u-foo',
129
    'x-en-u-foo-u-bar'
130
];
129
];
131
for (var validLanguageTag of validLanguageTags)
130
for (var validLanguageTag of validLanguageTags)
132
    shouldNotThrow(() => Intl.PluralRules.supportedLocalesOf(validLanguageTag));
131
    shouldNotThrow(() => Intl.PluralRules.supportedLocalesOf(validLanguageTag));
- a/JSTests/stress/intl-relativetimeformat.js -8 / +8 lines
Lines 69-77 function shouldThrow(func, errorType) { a/JSTests/stress/intl-relativetimeformat.js_sec1
69
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
69
        ? '["en-Latn-US-1abc-foobar-variant-a-aa-aaa-u-kn-x-reserved"]'
70
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
70
        : '["en-Latn-US-variant-foobar-1abc-a-aa-aaa-u-kn-true-x-reserved"]'
71
);
71
);
72
shouldBe(JSON.stringify(Intl.RelativeTimeFormat.supportedLocalesOf('no-bok')), '["nb"]');
73
shouldBe(JSON.stringify(Intl.RelativeTimeFormat.supportedLocalesOf('x-some-thing')), '[]');
74
72
73
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('no-bok'), RangeError);
74
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('x-some-thing'), RangeError);
75
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf(Object.create(null, { length: { get() { throw new Error(); } } })), Error);
75
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf(Object.create(null, { length: { get() { throw new Error(); } } })), Error);
76
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error(); } } })), Error);
76
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error(); } } })), Error);
77
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf([{ toString() { throw new Error(); } }]), Error);
77
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf([{ toString() { throw new Error(); } }]), Error);
Lines 87-92 function shouldThrow(func, errorType) { a/JSTests/stress/intl-relativetimeformat.js_sec2
87
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('en-*'), RangeError);
87
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('en-*'), RangeError);
88
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('en-'), RangeError);
88
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('en-'), RangeError);
89
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('en--US'), RangeError);
89
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('en--US'), RangeError);
90
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('i-klingon'), RangeError); // grandfathered tag is not accepted by IsStructurallyValidLanguageTag
91
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('x-en-US-12345'), RangeError);
92
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('x-12345-12345-en-US'), RangeError);
93
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('x-en-US-12345-12345'), RangeError);
94
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('x-en-u-foo'), RangeError);
95
shouldThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf('x-en-u-foo-u-bar'), RangeError);
90
96
91
const validLanguageTags = [
97
const validLanguageTags = [
92
    'de', // ISO 639 language code
98
    'de', // ISO 639 language code
Lines 98-113 function shouldThrow(func, errorType) { a/JSTests/stress/intl-relativetimeformat.js_sec3
98
    'cmn-hans-cn', // + ISO 3166-1 country code
104
    'cmn-hans-cn', // + ISO 3166-1 country code
99
    'es-419', // + UN M.49 region code
105
    'es-419', // + UN M.49 region code
100
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
106
    'es-419-u-nu-latn-cu-bob', // + Unicode locale extension sequence
101
    'i-klingon', // grandfathered tag
102
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
107
    'cmn-hans-cn-t-ca-u-ca-x-t-u', // singleton subtags can also be used as private use subtags
103
    'enochian-enochian', // language and variant subtags may be the same
108
    'enochian-enochian', // language and variant subtags may be the same
104
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
109
    'de-gregory-u-ca-gregory', // variant and extension subtags may be the same
105
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
110
    'aa-a-foo-x-a-foo-bar', // variant subtags can also be used as private use subtags
106
    'x-en-US-12345', // anything goes in private use tags
107
    'x-12345-12345-en-US',
108
    'x-en-US-12345-12345',
109
    'x-en-u-foo',
110
    'x-en-u-foo-u-bar'
111
];
111
];
112
for (let validLanguageTag of validLanguageTags)
112
for (let validLanguageTag of validLanguageTags)
113
    shouldNotThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf(validLanguageTag));
113
    shouldNotThrow(() => Intl.RelativeTimeFormat.supportedLocalesOf(validLanguageTag));
- a/JSTests/stress/string-toLocaleLowerCase.js -2 / +8 lines
Lines 30-37 function shouldThrow(func, errorType) { a/JSTests/stress/string-toLocaleLowerCase.js_sec1
30
shouldBe('A'.toLocaleLowerCase(9), 'a');
30
shouldBe('A'.toLocaleLowerCase(9), 'a');
31
// Handles array-like objects with holes.
31
// Handles array-like objects with holes.
32
shouldBe('\u0130'.toLocaleLowerCase({ length: 4, 1: 'az', 3: 'en' }), 'i');
32
shouldBe('\u0130'.toLocaleLowerCase({ length: 4, 1: 'az', 3: 'en' }), 'i');
33
// Doesn't throw, but ignores private tags.
34
shouldBe('A'.toLocaleLowerCase('x-some-thing'), 'a');
35
// Throws on problems with length, get, or toString.
33
// Throws on problems with length, get, or toString.
36
shouldThrow(() => 'A'.toLocaleLowerCase(Object.create(null, { length: { get() { throw new Error() } } })), Error);
34
shouldThrow(() => 'A'.toLocaleLowerCase(Object.create(null, { length: { get() { throw new Error() } } })), Error);
37
shouldThrow(() => 'A'.toLocaleLowerCase(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error() } } })), Error);
35
shouldThrow(() => 'A'.toLocaleLowerCase(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error() } } })), Error);
Lines 49-54 function shouldThrow(func, errorType) { a/JSTests/stress/string-toLocaleLowerCase.js_sec2
49
shouldThrow(() => 'A'.toLocaleLowerCase('en-*'), RangeError);
47
shouldThrow(() => 'A'.toLocaleLowerCase('en-*'), RangeError);
50
shouldThrow(() => 'A'.toLocaleLowerCase('en-'), RangeError);
48
shouldThrow(() => 'A'.toLocaleLowerCase('en-'), RangeError);
51
shouldThrow(() => 'A'.toLocaleLowerCase('en--US'), RangeError);
49
shouldThrow(() => 'A'.toLocaleLowerCase('en--US'), RangeError);
50
shouldThrow(() => 'A'.toLocaleLowerCase('no-bok'), RangeError);
51
shouldThrow(() => 'A'.toLocaleLowerCase('x-some-thing'), RangeError);
52
shouldThrow(() => 'A'.toLocaleLowerCase('i-klingon'), RangeError); // grandfathered tag is not accepted by IsStructurallyValidLanguageTag
53
shouldThrow(() => 'A'.toLocaleLowerCase('x-en-US-12345'), RangeError);
54
shouldThrow(() => 'A'.toLocaleLowerCase('x-12345-12345-en-US'), RangeError);
55
shouldThrow(() => 'A'.toLocaleLowerCase('x-en-US-12345-12345'), RangeError);
56
shouldThrow(() => 'A'.toLocaleLowerCase('x-en-u-foo'), RangeError);
57
shouldThrow(() => 'A'.toLocaleLowerCase('x-en-u-foo-u-bar'), RangeError);
52
58
53
// Check ascii and accents.
59
// Check ascii and accents.
54
shouldBe('AbCdEfGhIjKlMnOpQRStuvWXyZ0123456789'.toLocaleLowerCase(), 'abcdefghijklmnopqrstuvwxyz0123456789');
60
shouldBe('AbCdEfGhIjKlMnOpQRStuvWXyZ0123456789'.toLocaleLowerCase(), 'abcdefghijklmnopqrstuvwxyz0123456789');
- a/JSTests/stress/string-toLocaleUpperCase.js -2 / +8 lines
Lines 30-37 function shouldThrow(func, errorType) { a/JSTests/stress/string-toLocaleUpperCase.js_sec1
30
shouldBe('a'.toLocaleUpperCase(9), 'A');
30
shouldBe('a'.toLocaleUpperCase(9), 'A');
31
// Handles array-like objects with holes.
31
// Handles array-like objects with holes.
32
shouldBe('i'.toLocaleUpperCase({ length: 4, 1: 'az', 3: 'en' }), '\u0130');
32
shouldBe('i'.toLocaleUpperCase({ length: 4, 1: 'az', 3: 'en' }), '\u0130');
33
// Doesn't throw, but ignores private tags.
34
shouldBe('a'.toLocaleUpperCase('x-some-thing'), 'A');
35
// Throws on problems with length, get, or toString.
33
// Throws on problems with length, get, or toString.
36
shouldThrow(() => 'a'.toLocaleUpperCase(Object.create(null, { length: { get() { throw new Error() } } })), Error);
34
shouldThrow(() => 'a'.toLocaleUpperCase(Object.create(null, { length: { get() { throw new Error() } } })), Error);
37
shouldThrow(() => 'a'.toLocaleUpperCase(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error() } } })), Error);
35
shouldThrow(() => 'a'.toLocaleUpperCase(Object.create(null, { length: { value: 1 }, 0: { get() { throw new Error() } } })), Error);
Lines 49-54 function shouldThrow(func, errorType) { a/JSTests/stress/string-toLocaleUpperCase.js_sec2
49
shouldThrow(() => 'a'.toLocaleUpperCase('en-*'), RangeError);
47
shouldThrow(() => 'a'.toLocaleUpperCase('en-*'), RangeError);
50
shouldThrow(() => 'a'.toLocaleUpperCase('en-'), RangeError);
48
shouldThrow(() => 'a'.toLocaleUpperCase('en-'), RangeError);
51
shouldThrow(() => 'a'.toLocaleUpperCase('en--US'), RangeError);
49
shouldThrow(() => 'a'.toLocaleUpperCase('en--US'), RangeError);
50
shouldThrow(() => 'A'.toLocaleUpperCase('no-bok'), RangeError);
51
shouldThrow(() => 'A'.toLocaleUpperCase('x-some-thing'), RangeError);
52
shouldThrow(() => 'A'.toLocaleUpperCase('i-klingon'), RangeError); // grandfathered tag is not accepted by IsStructurallyValidLanguageTag
53
shouldThrow(() => 'A'.toLocaleUpperCase('x-en-US-12345'), RangeError);
54
shouldThrow(() => 'A'.toLocaleUpperCase('x-12345-12345-en-US'), RangeError);
55
shouldThrow(() => 'A'.toLocaleUpperCase('x-en-US-12345-12345'), RangeError);
56
shouldThrow(() => 'A'.toLocaleUpperCase('x-en-u-foo'), RangeError);
57
shouldThrow(() => 'A'.toLocaleUpperCase('x-en-u-foo-u-bar'), RangeError);
52
58
53
// Check ascii and accents.
59
// Check ascii and accents.
54
shouldBe('AbCdEfGhIjKlMnOpQRStuvWXyZ0123456789'.toLocaleUpperCase(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
60
shouldBe('AbCdEfGhIjKlMnOpQRStuvWXyZ0123456789'.toLocaleUpperCase(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
- a/JSTests/test262/expectations.yaml -37 / +4 lines
Lines 1584-1592 test/intl402/Intl/getCanonicalLocales/complex-region-subtag-replacement.js: a/JSTests/test262/expectations.yaml_sec1
1584
test/intl402/Intl/getCanonicalLocales/grandfathered.js:
1584
test/intl402/Intl/getCanonicalLocales/grandfathered.js:
1585
  default: 'Test262Error: Expected SameValue(«cmn», «zh») to be true'
1585
  default: 'Test262Error: Expected SameValue(«cmn», «zh») to be true'
1586
  strict mode: 'Test262Error: Expected SameValue(«cmn», «zh») to be true'
1586
  strict mode: 'Test262Error: Expected SameValue(«cmn», «zh») to be true'
1587
test/intl402/Intl/getCanonicalLocales/invalid-tags.js:
1588
  default: 'Test262Error: Language tag: no-nyn Expected a RangeError to be thrown but no exception was thrown at all'
1589
  strict mode: 'Test262Error: Language tag: no-nyn Expected a RangeError to be thrown but no exception was thrown at all'
1590
test/intl402/Intl/getCanonicalLocales/non-iana-canon.js:
1587
test/intl402/Intl/getCanonicalLocales/non-iana-canon.js:
1591
  default: 'Test262Error: The value of Intl.getCanonicalLocales(tag)[0] equals the value of `canonical` Expected SameValue(«en-US-u-va-posix», «posix») to be true'
1588
  default: 'Test262Error: The value of Intl.getCanonicalLocales(tag)[0] equals the value of `canonical` Expected SameValue(«en-US-u-va-posix», «posix») to be true'
1592
  strict mode: 'Test262Error: The value of Intl.getCanonicalLocales(tag)[0] equals the value of `canonical` Expected SameValue(«en-US-u-va-posix», «posix») to be true'
1589
  strict mode: 'Test262Error: The value of Intl.getCanonicalLocales(tag)[0] equals the value of `canonical` Expected SameValue(«en-US-u-va-posix», «posix») to be true'
Lines 1599-1607 test/intl402/Intl/getCanonicalLocales/preferred-variant.js: a/JSTests/test262/expectations.yaml_sec2
1599
test/intl402/Intl/getCanonicalLocales/transformed-ext-canonical.js:
1596
test/intl402/Intl/getCanonicalLocales/transformed-ext-canonical.js:
1600
  default: 'Test262Error: Expected SameValue(«sl-t-sl-rozaj-biske-1994», «sl-t-sl-1994-biske-rozaj») to be true'
1597
  default: 'Test262Error: Expected SameValue(«sl-t-sl-rozaj-biske-1994», «sl-t-sl-1994-biske-rozaj») to be true'
1601
  strict mode: 'Test262Error: Expected SameValue(«sl-t-sl-rozaj-biske-1994», «sl-t-sl-1994-biske-rozaj») to be true'
1598
  strict mode: 'Test262Error: Expected SameValue(«sl-t-sl-rozaj-biske-1994», «sl-t-sl-1994-biske-rozaj») to be true'
1602
test/intl402/Intl/getCanonicalLocales/transformed-ext-invalid.js:
1603
  default: 'Test262Error: en-t-root Expected a RangeError to be thrown but no exception was thrown at all'
1604
  strict mode: 'Test262Error: en-t-root Expected a RangeError to be thrown but no exception was thrown at all'
1605
test/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-region.js:
1599
test/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-region.js:
1606
  default: 'Test262Error: Expected SameValue(«und-u-rg-no23», «und-u-rg-no50») to be true'
1600
  default: 'Test262Error: Expected SameValue(«und-u-rg-no23», «und-u-rg-no50») to be true'
1607
  strict mode: 'Test262Error: Expected SameValue(«und-u-rg-no23», «und-u-rg-no50») to be true'
1601
  strict mode: 'Test262Error: Expected SameValue(«und-u-rg-no23», «und-u-rg-no50») to be true'
Lines 1612-1631 test/intl402/Intl/getCanonicalLocales/unicode-ext-canonicalize-yes-to-true.js: a/JSTests/test262/expectations.yaml_sec3
1612
  default: 'Test262Error: Expected SameValue(«und-u-kb-true», «und-u-kb») to be true'
1606
  default: 'Test262Error: Expected SameValue(«und-u-kb-true», «und-u-kb») to be true'
1613
  strict mode: 'Test262Error: Expected SameValue(«und-u-kb-true», «und-u-kb») to be true'
1607
  strict mode: 'Test262Error: Expected SameValue(«und-u-kb-true», «und-u-kb») to be true'
1614
test/intl402/Intl/getCanonicalLocales/unicode-ext-key-with-digit.js:
1608
test/intl402/Intl/getCanonicalLocales/unicode-ext-key-with-digit.js:
1615
  default: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1609
  default: 'Test262Error: Expected SameValue(«en-u-0c-yes», «en-u-0c») to be true'
1616
  strict mode: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1610
  strict mode: 'Test262Error: Expected SameValue(«en-u-0c-yes», «en-u-0c») to be true'
1617
test/intl402/Locale/constructor-apply-options-canonicalizes-twice.js:
1611
test/intl402/Locale/constructor-apply-options-canonicalizes-twice.js:
1618
  default: 'Test262Error: Expected SameValue(«ru-Armn-SU», «ru-Armn-AM») to be true'
1612
  default: 'Test262Error: Expected SameValue(«ru-Armn-SU», «ru-Armn-AM») to be true'
1619
  strict mode: 'Test262Error: Expected SameValue(«ru-Armn-SU», «ru-Armn-AM») to be true'
1613
  strict mode: 'Test262Error: Expected SameValue(«ru-Armn-SU», «ru-Armn-AM») to be true'
1620
test/intl402/Locale/constructor-non-iana-canon.js:
1614
test/intl402/Locale/constructor-non-iana-canon.js:
1621
  default: 'Test262Error: new Intl.Locale("mo").maximize().toString() returns "ro-Latn-RO" Expected SameValue(«ro», «ro-Latn-RO») to be true'
1615
  default: 'Test262Error: new Intl.Locale("mo").maximize().toString() returns "ro-Latn-RO" Expected SameValue(«ro», «ro-Latn-RO») to be true'
1622
  strict mode: 'Test262Error: new Intl.Locale("mo").maximize().toString() returns "ro-Latn-RO" Expected SameValue(«ro», «ro-Latn-RO») to be true'
1616
  strict mode: 'Test262Error: new Intl.Locale("mo").maximize().toString() returns "ro-Latn-RO" Expected SameValue(«ro», «ro-Latn-RO») to be true'
1623
test/intl402/Locale/constructor-options-language-valid-undefined.js:
1624
  default: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1625
  strict mode: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1626
test/intl402/Locale/constructor-options-language-valid.js:
1627
  default: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1628
  strict mode: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1629
test/intl402/Locale/constructor-options-numeric-undefined.js:
1617
test/intl402/Locale/constructor-options-numeric-undefined.js:
1630
  default: 'Test262Error: new Intl.Locale("en-u-kn-true", {numeric: undefined}).toString() returns "en-u-kn" Expected SameValue(«en-u-kn-true», «en-u-kn») to be true'
1618
  default: 'Test262Error: new Intl.Locale("en-u-kn-true", {numeric: undefined}).toString() returns "en-u-kn" Expected SameValue(«en-u-kn-true», «en-u-kn») to be true'
1631
  strict mode: 'Test262Error: new Intl.Locale("en-u-kn-true", {numeric: undefined}).toString() returns "en-u-kn" Expected SameValue(«en-u-kn-true», «en-u-kn») to be true'
1619
  strict mode: 'Test262Error: new Intl.Locale("en-u-kn-true", {numeric: undefined}).toString() returns "en-u-kn" Expected SameValue(«en-u-kn-true», «en-u-kn») to be true'
Lines 1635-1676 test/intl402/Locale/constructor-options-numeric-valid.js: a/JSTests/test262/expectations.yaml_sec4
1635
test/intl402/Locale/constructor-options-region-valid.js:
1623
test/intl402/Locale/constructor-options-region-valid.js:
1636
  default: "Test262Error: new Intl.Locale('en', {region: \"554\"}).toString() returns \"en-NZ\" Expected SameValue(«en-554», «en-NZ») to be true"
1624
  default: "Test262Error: new Intl.Locale('en', {region: \"554\"}).toString() returns \"en-NZ\" Expected SameValue(«en-554», «en-NZ») to be true"
1637
  strict mode: "Test262Error: new Intl.Locale('en', {region: \"554\"}).toString() returns \"en-NZ\" Expected SameValue(«en-554», «en-NZ») to be true"
1625
  strict mode: "Test262Error: new Intl.Locale('en', {region: \"554\"}).toString() returns \"en-NZ\" Expected SameValue(«en-554», «en-NZ») to be true"
1638
test/intl402/Locale/constructor-parse-twice.js:
1639
  default: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1640
  strict mode: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1641
test/intl402/Locale/constructor-tag.js:
1626
test/intl402/Locale/constructor-tag.js:
1642
  default: 'Test262Error: new Intl.Locale("sl-ROZAJ-BISKE-1994").toString() returns "sl-1994-biske-rozaj" Expected SameValue(«sl-rozaj-biske-1994», «sl-1994-biske-rozaj») to be true'
1627
  default: 'Test262Error: new Intl.Locale("sl-ROZAJ-BISKE-1994").toString() returns "sl-1994-biske-rozaj" Expected SameValue(«sl-rozaj-biske-1994», «sl-1994-biske-rozaj») to be true'
1643
  strict mode: 'Test262Error: new Intl.Locale("sl-ROZAJ-BISKE-1994").toString() returns "sl-1994-biske-rozaj" Expected SameValue(«sl-rozaj-biske-1994», «sl-1994-biske-rozaj») to be true'
1628
  strict mode: 'Test262Error: new Intl.Locale("sl-ROZAJ-BISKE-1994").toString() returns "sl-1994-biske-rozaj" Expected SameValue(«sl-rozaj-biske-1994», «sl-1994-biske-rozaj») to be true'
1644
test/intl402/Locale/extensions-grandfathered.js:
1645
  default: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1646
  strict mode: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1647
test/intl402/Locale/extensions-private.js:
1648
  default: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1649
  strict mode: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1650
test/intl402/Locale/getters-grandfathered.js:
1651
  default: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1652
  strict mode: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1653
test/intl402/Locale/getters.js:
1629
test/intl402/Locale/getters.js:
1654
  default: 'Test262Error: Expected SameValue(«de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-true-kn-false-nu-latn», «de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-kn-false-nu-latn») to be true'
1630
  default: 'Test262Error: Expected SameValue(«de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-true-kn-false-nu-latn», «de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-kn-false-nu-latn») to be true'
1655
  strict mode: 'Test262Error: Expected SameValue(«de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-true-kn-false-nu-latn», «de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-kn-false-nu-latn») to be true'
1631
  strict mode: 'Test262Error: Expected SameValue(«de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-true-kn-false-nu-latn», «de-Latn-DE-u-ca-gregory-co-phonebk-hc-h23-kf-kn-false-nu-latn») to be true'
1656
test/intl402/Locale/invalid-tag-throws.js:
1657
  default: 'Test262Error: no-nyn is an invalid tag value Expected a RangeError to be thrown but no exception was thrown at all'
1658
  strict mode: 'Test262Error: no-nyn is an invalid tag value Expected a RangeError to be thrown but no exception was thrown at all'
1659
test/intl402/Locale/likely-subtags-grandfathered.js:
1632
test/intl402/Locale/likely-subtags-grandfathered.js:
1660
  default: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1633
  default: 'Test262Error: Expected SameValue(«cmn», «zh») to be true'
1661
  strict mode: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all'
1634
  strict mode: 'Test262Error: Expected SameValue(«cmn», «zh») to be true'
1662
test/intl402/Locale/likely-subtags.js:
1635
test/intl402/Locale/likely-subtags.js:
1663
  default: 'Test262Error: "en-u-co".maximize() should be "en-Latn-US-u-co" Expected SameValue(«en-Latn-US-u-co-yes», «en-Latn-US-u-co») to be true'
1636
  default: 'Test262Error: "en-u-co".maximize() should be "en-Latn-US-u-co" Expected SameValue(«en-Latn-US-u-co-yes», «en-Latn-US-u-co») to be true'
1664
  strict mode: 'Test262Error: "en-u-co".maximize() should be "en-Latn-US-u-co" Expected SameValue(«en-Latn-US-u-co-yes», «en-Latn-US-u-co») to be true'
1637
  strict mode: 'Test262Error: "en-u-co".maximize() should be "en-Latn-US-u-co" Expected SameValue(«en-Latn-US-u-co-yes», «en-Latn-US-u-co») to be true'
1665
test/intl402/Locale/prototype/minimize/removing-likely-subtags-first-adds-likely-subtags.js:
1638
test/intl402/Locale/prototype/minimize/removing-likely-subtags-first-adds-likely-subtags.js:
1666
  default: 'Test262Error: "und".minimize() should be "en" Expected SameValue(«en-u-va-posix», «en») to be true'
1639
  default: 'Test262Error: "und".minimize() should be "en" Expected SameValue(«en-u-va-posix», «en») to be true'
1667
  strict mode: 'Test262Error: "und".minimize() should be "en" Expected SameValue(«en-u-va-posix», «en») to be true'
1640
  strict mode: 'Test262Error: "und".minimize() should be "en" Expected SameValue(«en-u-va-posix», «en») to be true'
1668
test/intl402/RelativeTimeFormat/constructor/constructor/locales-valid.js:
1669
  default: 'Test262Error: Grandfathered Expected a RangeError to be thrown but no exception was thrown at all'
1670
  strict mode: 'Test262Error: Grandfathered Expected a RangeError to be thrown but no exception was thrown at all'
1671
test/intl402/language-tags-invalid.js:
1672
  default: 'Test262Error: Invalid language tag no-nyn was not rejected. Expected a RangeError to be thrown but no exception was thrown at all (Testing with Collator.)'
1673
  strict mode: 'Test262Error: Invalid language tag no-nyn was not rejected. Expected a RangeError to be thrown but no exception was thrown at all (Testing with Collator.)'
1674
test/language/arguments-object/mapped/nonconfigurable-nonenumerable-nonwritable-descriptors-set-by-arguments.js:
1641
test/language/arguments-object/mapped/nonconfigurable-nonenumerable-nonwritable-descriptors-set-by-arguments.js:
1675
  default: 'Test262Error: Expected obj[0] to have enumerable:false.'
1642
  default: 'Test262Error: Expected obj[0] to have enumerable:false.'
1676
test/language/arguments-object/mapped/nonconfigurable-nonenumerable-nonwritable-descriptors-set-by-param.js:
1643
test/language/arguments-object/mapped/nonconfigurable-nonenumerable-nonwritable-descriptors-set-by-param.js:

Return to Bug 215058