Changeset 267102 in webkit


Ignore:
Timestamp:
Sep 15, 2020 2:58:32 PM (4 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Intl.Collator should take collation option
https://bugs.webkit.org/show_bug.cgi?id=216529

Reviewed by Ross Kirsling.

JSTests:

  • stress/intl-collator-co-extension.js:

(shouldThrow):

Source/JavaScriptCore:

This patch adds "collation" option to Intl.Collator. We are already getting consensus[1], and will be integrated into the spec.
Previously, passing "collation" is only available through "-u-co-" unicode extension in the passed locale. The proposal exposes
collation option as an option to Intl.Collator so that we can set it easily.
"collation" is used only when "usage" is "sort". "search" usage will filter out collation options since "search" itself is one of
the "collation" option.

[1]: https://github.com/tc39/ecma402/pull/459

  • runtime/IntlCollator.cpp:

(JSC::IntlCollator::sortLocaleData):
(JSC::IntlCollator::initializeCollator):

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r267062 r267102  
     12020-09-14  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Intl.Collator should take collation option
     4        https://bugs.webkit.org/show_bug.cgi?id=216529
     5
     6        Reviewed by Ross Kirsling.
     7
     8        * stress/intl-collator-co-extension.js:
     9        (shouldThrow):
     10
    1112020-09-14  Keith Miller  <keith_miller@apple.com>
    212
  • trunk/JSTests/stress/intl-collator-co-extension.js

    r266973 r267102  
    1616}
    1717
     18function shouldThrow(func, errorMessage) {
     19    var errorThrown = false;
     20    var error = null;
     21    try {
     22        func();
     23    } catch (e) {
     24        errorThrown = true;
     25        error = e;
     26    }
     27    if (!errorThrown)
     28        throw new Error('not thrown');
     29    if (String(error) !== errorMessage)
     30        throw new Error(`bad error: ${String(error)}`);
     31}
     32
    1833shouldBeArray(["AE", "\u00C4"].sort(new Intl.Collator("de", {usage: "sort"}).compare), ["\u00C4", "AE"]);
    1934shouldBeArray(["AE", "\u00C4"].sort(new Intl.Collator("de", {usage: "search"}).compare), ["AE", "\u00C4"]);
    2035shouldBe(new Intl.Collator("de", {usage: "sort"}).resolvedOptions().locale, "de");
    2136shouldBe(new Intl.Collator("de", {usage: "search"}).resolvedOptions().locale, "de");
     37shouldBe(new Intl.Collator("de", {usage: "sort", collation: "phonebk"}).resolvedOptions().locale, "de");
    2238shouldBeArray(["2", "10"].sort(new Intl.Collator("de", {usage: "sort"}).compare), ["10", "2"]);
    2339shouldBeArray(["2", "10"].sort(new Intl.Collator("de", {usage: "search"}).compare), ["10", "2"]);
     
    4157
    4258shouldBeArray(["a", "ae", "ä", "æ"].sort(new Intl.Collator("de-u-co-phonebk").compare), ["a", "ae", "ä", "æ"]);
     59shouldBeArray(["a", "ae", "ä", "æ"].sort(new Intl.Collator("de", { collation: 'phonebk' }).compare), ["a", "ae", "ä", "æ"]);
    4360shouldBeArray(["a", "ae", "ä", "æ"].sort(new Intl.Collator("de").compare), ["a", "ä", "ae", "æ"]);
    4461shouldBeArray(["a", "ae", "ä", "æ"].sort(new Intl.Collator("de-u-co-phonebk", { usage: 'search' }).compare), ["a", "ae", "ä", "æ"]);
     62shouldBeArray(["a", "ae", "ä", "æ"].sort(new Intl.Collator("de", { usage: 'search', collation: 'phonebk' }).compare), ["a", "ae", "ä", "æ"]);
    4563shouldBeArray(["a", "ae", "ä", "æ"].sort(new Intl.Collator("de", { usage: 'search' }).compare), ["a", "ae", "ä", "æ"]);
     64
     65// We cannot set sort / search / standard though "collation" option. Use "usage" instead.
     66shouldBe(new Intl.Collator("de-u-kn", {collation: "search"}).resolvedOptions().collation, "default");
     67shouldBe(new Intl.Collator("de-u-kn", {collation: "sort"}).resolvedOptions().collation, "default");
     68shouldBe(new Intl.Collator("de-u-kn", {collation: "standard"}).resolvedOptions().collation, "default");
     69shouldBe(new Intl.Collator("de-u-kn", {usage: "search", collation: "search"}).resolvedOptions().collation, "default");
     70shouldBe(new Intl.Collator("de-u-kn", {usage: "search", collation: "sort"}).resolvedOptions().collation, "default");
     71shouldBe(new Intl.Collator("de-u-kn", {usage: "search", collation: "standard"}).resolvedOptions().collation, "default");
     72
     73shouldThrow(() => {
     74    new Intl.Collator("de-u-kn", {"collation": "phonebook"});
     75}, `RangeError: collation is not a well-formed collation value`);
     76
     77shouldBe(new Intl.Collator("de-u-kn", {collation: "phonebk"}).resolvedOptions().collation, "phonebk");
     78shouldBe(new Intl.Collator("de-u-kn", {usage: "sort", collation: "phonebk"}).resolvedOptions().collation, "phonebk");
     79shouldBe(new Intl.Collator("de-u-kn", {usage: "search", collation: "phonebk"}).resolvedOptions().collation, "default");
     80shouldBe(new Intl.Collator("de-u-co-dict", {collation: "phonebk"}).resolvedOptions().collation, "phonebk");
     81shouldBe(new Intl.Collator("de-u-co-dict", {collation: "phonebk"}).resolvedOptions().locale, "de");
     82shouldBe(new Intl.Collator("de-u-co-dict", {usage: "search", collation: "phonebk"}).resolvedOptions().collation, "default");
     83shouldBe(new Intl.Collator("de-u-co-dict", {usage: "search", collation: "phonebk"}).resolvedOptions().locale, "de");
  • trunk/Source/JavaScriptCore/ChangeLog

    r267080 r267102  
     12020-09-14  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Intl.Collator should take collation option
     4        https://bugs.webkit.org/show_bug.cgi?id=216529
     5
     6        Reviewed by Ross Kirsling.
     7
     8        This patch adds "collation" option to Intl.Collator. We are already getting consensus[1], and will be integrated into the spec.
     9        Previously, passing "collation" is only available through "-u-co-" unicode extension in the passed locale. The proposal exposes
     10        collation option as an option to Intl.Collator so that we can set it easily.
     11        "collation" is used only when "usage" is "sort". "search" usage will filter out collation options since "search" itself is one of
     12        the "collation" option.
     13
     14        [1]: https://github.com/tc39/ecma402/pull/459
     15
     16        * runtime/IntlCollator.cpp:
     17        (JSC::IntlCollator::sortLocaleData):
     18        (JSC::IntlCollator::initializeCollator):
     19
    1202020-09-15  Joonghun Park  <jh718.park@samsung.com>
    221
  • trunk/Source/JavaScriptCore/runtime/IntlCollator.cpp

    r266178 r267102  
    8686
    8787        UErrorCode status = U_ZERO_ERROR;
    88         UEnumeration* enumeration = ucol_getKeywordValuesForLocale("collation", locale.utf8().data(), false, &status);
     88        auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucol_getKeywordValuesForLocale("collation", locale.utf8().data(), false, &status));
    8989        if (U_SUCCESS(status)) {
    9090            const char* collation;
    91             while ((collation = uenum_next(enumeration, nullptr, &status)) && U_SUCCESS(status)) {
     91            while ((collation = uenum_next(enumeration.get(), nullptr, &status)) && U_SUCCESS(status)) {
    9292                // 10.2.3 "The values "standard" and "search" must not be used as elements in any [[sortLocaleData]][locale].co and [[searchLocaleData]][locale].co array."
    9393                if (!strcmp(collation, "standard") || !strcmp(collation, "search"))
     
    9696                // Map keyword values to BCP 47 equivalents.
    9797                if (!strcmp(collation, "dictionary"))
    98                     collation = "dict";
     98                    keyLocaleData.append("dict"_s);
    9999                else if (!strcmp(collation, "gb2312han"))
    100                     collation = "gb2312";
     100                    keyLocaleData.append("gb2312"_s);
    101101                else if (!strcmp(collation, "phonebook"))
    102                     collation = "phonebk";
     102                    keyLocaleData.append("phonebk"_s);
    103103                else if (!strcmp(collation, "traditional"))
    104                     collation = "trad";
    105 
    106                 keyLocaleData.append(collation);
     104                    keyLocaleData.append("trad"_s);
     105                else
     106                    keyLocaleData.append(collation);
    107107            }
    108             uenum_close(enumeration);
    109108        }
    110109        break;
     
    179178    RETURN_IF_EXCEPTION(scope, void());
    180179
     180    {
     181        String collation = intlStringOption(globalObject, options, vm.propertyNames->collation, { }, nullptr, nullptr);
     182        RETURN_IF_EXCEPTION(scope, void());
     183        if (!collation.isNull()) {
     184            if (!isUnicodeLocaleIdentifierType(collation)) {
     185                throwRangeError(globalObject, scope, "collation is not a well-formed collation value"_s);
     186                return;
     187            }
     188            localeOptions[static_cast<unsigned>(RelevantExtensionKey::Co)] = WTFMove(collation);
     189        }
     190    }
     191
    181192    TriState numeric = intlBooleanOption(globalObject, options, vm.propertyNames->numeric);
    182193    RETURN_IF_EXCEPTION(scope, void());
     
    221232    switch (m_usage) {
    222233    case Usage::Sort:
    223         dataLocaleWithExtensions = m_locale.utf8();
     234        if (collation.isNull())
     235            dataLocaleWithExtensions = resolved.dataLocale.utf8();
     236        else
     237            dataLocaleWithExtensions = makeString(resolved.dataLocale, "-u-co-", m_collation).utf8();
    224238        break;
    225239    case Usage::Search:
     
    227241        // So we need to pass "co" unicode extension through locale. Since the other relevant extensions are handled via ucol_setAttribute,
    228242        // we can just use dataLocale
     243        // Since searchLocaleData filters out "co" unicode extension, "collation" option is just ignored.
    229244        dataLocaleWithExtensions = makeString(resolved.dataLocale, "-u-co-search").utf8();
    230245        break;
    231246    }
    232     dataLogLnIf(IntlCollatorInternal::verbose, "dataLocaleWithExtensions:(", dataLocaleWithExtensions, ")");
     247    dataLogLnIf(IntlCollatorInternal::verbose, "locale:(", resolved.locale, "),dataLocaleWithExtensions:(", dataLocaleWithExtensions, ")");
    233248
    234249    UErrorCode status = U_ZERO_ERROR;
Note: See TracChangeset for help on using the changeset viewer.