Changeset 281374 in webkit


Ignore:
Timestamp:
Aug 21, 2021 7:33:08 AM (11 months ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Intl Locale Info
https://bugs.webkit.org/show_bug.cgi?id=227830

Reviewed by Ross Kirsling.

JSTests:

  • stress/intl-locale-info.js: Added.

(shouldBe):
(throw.new.Error):
(let.enGB.new.Intl.Locale.shouldBe):
(let.l.new.Intl.Locale.shouldBe):

  • test262/config.yaml:

Source/JavaScriptCore:

This patch implements Intl.Locale's extension (Intl Locale Info proposal)[1], which is already stage 3.
Intl.Locale#{calendars,collations,hourCycles,numberingSystems,timeZones} can return array of preferred
configuration for the given locale. And Intl.Locale#textInfo can return text layout direction and Intl.Locale#weekInfo
can return weekday information (e.g. when weekend starts).

[1]: https://github.com/tc39/proposal-intl-locale-info

  • runtime/IntlLocale.cpp:

(JSC::createArrayFromStringVector):
(JSC::IntlLocale::calendars):
(JSC::IntlLocale::collations):
(JSC::IntlLocale::hourCycles):
(JSC::IntlLocale::numberingSystems):
(JSC::IntlLocale::timeZones):
(JSC::IntlLocale::textInfo):
(JSC::IntlLocale::weekInfo):

  • runtime/IntlLocale.h:
  • runtime/IntlLocalePrototype.cpp:

(JSC::JSC_DEFINE_CUSTOM_GETTER):

Location:
trunk
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r281371 r281374  
     12021-08-21  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Intl Locale Info
     4        https://bugs.webkit.org/show_bug.cgi?id=227830
     5
     6        Reviewed by Ross Kirsling.
     7
     8        * stress/intl-locale-info.js: Added.
     9        (shouldBe):
     10        (throw.new.Error):
     11        (let.enGB.new.Intl.Locale.shouldBe):
     12        (let.l.new.Intl.Locale.shouldBe):
     13        * test262/config.yaml:
     14
    1152021-08-21  Yusuke Suzuki  <ysuzuki@apple.com>
    216
  • trunk/JSTests/test262/config.yaml

    r281371 r281374  
    2525    - regexp-lookbehind
    2626    - cleanupSome
    27     - Intl.Locale-info
    2827    - resizable-arraybuffer
    2928    - Object.hasOwn
  • trunk/Source/JavaScriptCore/ChangeLog

    r281371 r281374  
     12021-08-21  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Intl Locale Info
     4        https://bugs.webkit.org/show_bug.cgi?id=227830
     5
     6        Reviewed by Ross Kirsling.
     7
     8        This patch implements Intl.Locale's extension (Intl Locale Info proposal)[1], which is already stage 3.
     9        Intl.Locale#{calendars,collations,hourCycles,numberingSystems,timeZones} can return array of preferred
     10        configuration for the given locale. And Intl.Locale#textInfo can return text layout direction and Intl.Locale#weekInfo
     11        can return weekday information (e.g. when weekend starts).
     12
     13        [1]: https://github.com/tc39/proposal-intl-locale-info
     14
     15        * runtime/IntlLocale.cpp:
     16        (JSC::createArrayFromStringVector):
     17        (JSC::IntlLocale::calendars):
     18        (JSC::IntlLocale::collations):
     19        (JSC::IntlLocale::hourCycles):
     20        (JSC::IntlLocale::numberingSystems):
     21        (JSC::IntlLocale::timeZones):
     22        (JSC::IntlLocale::textInfo):
     23        (JSC::IntlLocale::weekInfo):
     24        * runtime/IntlLocale.h:
     25        * runtime/IntlLocalePrototype.cpp:
     26        (JSC::JSC_DEFINE_CUSTOM_GETTER):
     27
    1282021-08-21  Yusuke Suzuki  <ysuzuki@apple.com>
    229
  • trunk/Source/JavaScriptCore/runtime/IntlCollator.cpp

    r278035 r281374  
    9191        auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucol_getKeywordValuesForLocale("collation", locale.utf8().data(), false, &status));
    9292        if (U_SUCCESS(status)) {
    93             const char* collation;
    94             while ((collation = uenum_next(enumeration.get(), nullptr, &status)) && U_SUCCESS(status)) {
     93            const char* pointer;
     94            int32_t length = 0;
     95            while ((pointer = uenum_next(enumeration.get(), &length, &status)) && U_SUCCESS(status)) {
    9596                // 10.2.3 "The values "standard" and "search" must not be used as elements in any [[sortLocaleData]][locale].co and [[searchLocaleData]][locale].co array."
    96                 if (!strcmp(collation, "standard") || !strcmp(collation, "search"))
     97                String collation(pointer, length);
     98                if (collation == "standard"_s || collation == "search"_s)
    9799                    continue;
    98 
    99                 // Map keyword values to BCP 47 equivalents.
    100                 if (!strcmp(collation, "dictionary"))
    101                     keyLocaleData.append("dict"_s);
    102                 else if (!strcmp(collation, "gb2312han"))
    103                     keyLocaleData.append("gb2312"_s);
    104                 else if (!strcmp(collation, "phonebook"))
    105                     keyLocaleData.append("phonebk"_s);
    106                 else if (!strcmp(collation, "traditional"))
    107                     keyLocaleData.append("trad"_s);
     100                if (auto mapped = mapICUCollationKeywordToBCP47(collation))
     101                    keyLocaleData.append(WTFMove(mapped.value()));
    108102                else
    109                     keyLocaleData.append(collation);
     103                    keyLocaleData.append(WTFMove(collation));
    110104            }
    111105        }
  • trunk/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp

    r281371 r281374  
    166166            String calendar = String(availableName, nameLength);
    167167            keyLocaleData.append(calendar);
    168             // Ensure aliases used in language tag are allowed.
    169             if (calendar == "gregorian")
    170                 keyLocaleData.append("gregory"_s);
    171             else if (calendar == "islamic-civil")
    172                 keyLocaleData.append("islamicc"_s);
    173             else if (calendar == "ethiopic-amete-alem")
    174                 keyLocaleData.append("ethioaa"_s);
     168            if (auto mapped = mapICUCalendarKeywordToBCP47(calendar))
     169                keyLocaleData.append(WTFMove(mapped.value()));
    175170        }
    176171        uenum_close(calendars);
  • trunk/Source/JavaScriptCore/runtime/IntlLocale.cpp

    r278859 r281374  
    3030#include "IntlObjectInlines.h"
    3131#include "JSCInlines.h"
     32#include <unicode/ucal.h>
     33#include <unicode/ucol.h>
     34#include <unicode/udat.h>
     35#include <unicode/udatpg.h>
    3236#include <unicode/uloc.h>
     37#include <unicode/unumsys.h>
    3338#include <wtf/unicode/icu/ICUHelpers.h>
    3439
     
    533538}
    534539
     540static inline JSArray* createArrayFromStringVector(JSGlobalObject* globalObject, Vector<String, 1>&& elements)
     541{
     542    VM& vm = globalObject->vm();
     543    auto scope = DECLARE_THROW_SCOPE(vm);
     544
     545    JSArray* result = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), elements.size());
     546    if (!result) {
     547        throwOutOfMemoryError(globalObject, scope);
     548        return nullptr;
     549    }
     550    for (unsigned index = 0; index < elements.size(); ++index) {
     551        result->putDirectIndex(globalObject, index, jsString(vm, WTFMove(elements[index])));
     552        RETURN_IF_EXCEPTION(scope, { });
     553    }
     554    return result;
     555}
     556
     557JSArray* IntlLocale::calendars(JSGlobalObject* globalObject)
     558{
     559    VM& vm = globalObject->vm();
     560    auto scope = DECLARE_THROW_SCOPE(vm);
     561
     562    Vector<String, 1> elements;
     563
     564    String preferred = calendar();
     565    if (!preferred.isEmpty()) {
     566        elements.append(WTFMove(preferred));
     567        RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     568    }
     569
     570    UErrorCode status = U_ZERO_ERROR;
     571    constexpr bool commonlyUsed = true;
     572    auto calendars = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucal_getKeywordValuesForLocale("calendar", m_localeID.data(), commonlyUsed, &status));
     573    if (!U_SUCCESS(status)) {
     574        throwTypeError(globalObject, scope, "invalid locale"_s);
     575        return nullptr;
     576    }
     577
     578    const char* pointer;
     579    int32_t length = 0;
     580    while ((pointer = uenum_next(calendars.get(), &length, &status)) && U_SUCCESS(status)) {
     581        String calendar(pointer, length);
     582        if (auto mapped = mapICUCalendarKeywordToBCP47(calendar))
     583            elements.append(WTFMove(mapped.value()));
     584        else
     585            elements.append(WTFMove(calendar));
     586    }
     587    if (!U_SUCCESS(status)) {
     588        throwTypeError(globalObject, scope, "invalid locale"_s);
     589        return nullptr;
     590    }
     591
     592    RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     593}
     594
     595JSArray* IntlLocale::collations(JSGlobalObject* globalObject)
     596{
     597    VM& vm = globalObject->vm();
     598    auto scope = DECLARE_THROW_SCOPE(vm);
     599
     600    Vector<String, 1> elements;
     601
     602    String preferred = collation();
     603    if (!preferred.isEmpty()) {
     604        elements.append(WTFMove(preferred));
     605        RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     606    }
     607
     608    UErrorCode status = U_ZERO_ERROR;
     609    constexpr bool commonlyUsed = true;
     610    auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucol_getKeywordValuesForLocale("collation", m_localeID.data(), commonlyUsed, &status));
     611    if (!U_SUCCESS(status)) {
     612        throwTypeError(globalObject, scope, "invalid locale"_s);
     613        return nullptr;
     614    }
     615
     616    const char* pointer;
     617    int32_t length = 0;
     618    while ((pointer = uenum_next(enumeration.get(), &length, &status)) && U_SUCCESS(status)) {
     619        String collation(pointer, length);
     620        // 1.1.3 step 4, The values "standard" and "search" must be excluded from list.
     621        if (collation == "standard"_s || collation == "search"_s)
     622            continue;
     623        if (auto mapped = mapICUCollationKeywordToBCP47(collation))
     624            elements.append(WTFMove(mapped.value()));
     625        else
     626            elements.append(WTFMove(collation));
     627    }
     628    if (!U_SUCCESS(status)) {
     629        throwTypeError(globalObject, scope, "invalid locale"_s);
     630        return nullptr;
     631    }
     632
     633    RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     634}
     635
     636JSArray* IntlLocale::hourCycles(JSGlobalObject* globalObject)
     637{
     638    VM& vm = globalObject->vm();
     639    auto scope = DECLARE_THROW_SCOPE(vm);
     640
     641    Vector<String, 1> elements;
     642
     643    String preferred = hourCycle();
     644    if (!preferred.isEmpty()) {
     645        elements.append(WTFMove(preferred));
     646        RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     647    }
     648
     649    UErrorCode status = U_ZERO_ERROR;
     650    auto generator = std::unique_ptr<UDateTimePatternGenerator, ICUDeleter<udatpg_close>>(udatpg_open(m_localeID.data(), &status));
     651    if (U_FAILURE(status))
     652        return nullptr;
     653
     654    // Use "j" skeleton and parse pattern to retrieve the configured hour-cycle information.
     655    constexpr const UChar skeleton[] = { 'j', 0 };
     656    Vector<UChar, 32> pattern;
     657    status = callBufferProducingFunction(udatpg_getBestPatternWithOptions, generator.get(), skeleton, 1, UDATPG_MATCH_HOUR_FIELD_LENGTH, pattern);
     658    if (!U_SUCCESS(status)) {
     659        throwTypeError(globalObject, scope, "invalid locale"_s);
     660        return nullptr;
     661    }
     662
     663    for (unsigned i = 0; i < pattern.size(); ++i) {
     664        UChar currentCharacter = pattern[i];
     665        if (!isASCIIAlpha(currentCharacter))
     666            continue;
     667
     668        while (i + 1 < pattern.size() && pattern[i + 1] == currentCharacter)
     669            ++i;
     670
     671        switch (currentCharacter) {
     672        case 'h': {
     673            elements.append("h12"_s);
     674            RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     675        }
     676        case 'H': {
     677            elements.append("h23"_s);
     678            RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     679        }
     680        case 'k': {
     681            elements.append("h24"_s);
     682            RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     683        }
     684        case 'K': {
     685            elements.append("h11"_s);
     686            RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     687        }
     688        default:
     689            break;
     690        }
     691    }
     692
     693    RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     694}
     695
     696JSArray* IntlLocale::numberingSystems(JSGlobalObject* globalObject)
     697{
     698    VM& vm = globalObject->vm();
     699    auto scope = DECLARE_THROW_SCOPE(vm);
     700
     701    Vector<String, 1> elements;
     702    String preferred = numberingSystem();
     703    if (!preferred.isEmpty()) {
     704        elements.append(WTFMove(preferred));
     705        RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     706    }
     707
     708    UErrorCode status = U_ZERO_ERROR;
     709    auto numberingSystem = std::unique_ptr<UNumberingSystem, ICUDeleter<unumsys_close>>(unumsys_open(m_localeID.data(), &status));
     710    if (!U_SUCCESS(status)) {
     711        throwTypeError(globalObject, scope, "invalid locale"_s);
     712        return nullptr;
     713    }
     714    elements.append(unumsys_getName(numberingSystem.get()));
     715
     716    RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     717}
     718
     719JSValue IntlLocale::timeZones(JSGlobalObject* globalObject)
     720{
     721    VM& vm = globalObject->vm();
     722    auto scope = DECLARE_THROW_SCOPE(vm);
     723
     724    Vector<String, 1> elements;
     725
     726    // 11.6-3 Let region be the substring of locale corresponding to the unicode_region_subtag production of the unicode_language_id.
     727    String region = this->region();
     728    if (region.isEmpty())
     729        return jsUndefined();
     730
     731    UErrorCode status = U_ZERO_ERROR;
     732    auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, region.utf8().data(), nullptr, &status));
     733    if (!U_SUCCESS(status)) {
     734        throwTypeError(globalObject, scope, "invalid locale"_s);
     735        return { };
     736    }
     737
     738    int32_t length;
     739    const char* collation;
     740    while ((collation = uenum_next(enumeration.get(), &length, &status)) && U_SUCCESS(status))
     741        elements.constructAndAppend(collation, length);
     742    if (!U_SUCCESS(status)) {
     743        throwTypeError(globalObject, scope, "invalid locale"_s);
     744        return { };
     745    }
     746
     747    RELEASE_AND_RETURN(scope, createArrayFromStringVector(globalObject, WTFMove(elements)));
     748}
     749
     750JSObject* IntlLocale::textInfo(JSGlobalObject* globalObject)
     751{
     752    VM& vm = globalObject->vm();
     753    auto scope = DECLARE_THROW_SCOPE(vm);
     754
     755    UErrorCode status = U_ZERO_ERROR;
     756    ULayoutType layout = uloc_getCharacterOrientation(m_localeID.data(), &status);
     757    if (!U_SUCCESS(status)) {
     758        throwTypeError(globalObject, scope, "invalid locale"_s);
     759        return nullptr;
     760    }
     761
     762    JSString* layoutString = nullptr;
     763    switch (layout) {
     764    default:
     765    case ULOC_LAYOUT_LTR:
     766        layoutString = jsString(vm, "ltr"_s);
     767        break;
     768    case ULOC_LAYOUT_RTL:
     769        layoutString = jsString(vm, "rtl"_s);
     770        break;
     771    case ULOC_LAYOUT_TTB:
     772        layoutString = jsString(vm, "ttb"_s);
     773        break;
     774    case ULOC_LAYOUT_BTT:
     775        layoutString = jsString(vm, "btt"_s);
     776        break;
     777    }
     778
     779    JSObject* result = constructEmptyObject(globalObject);
     780    result->putDirect(vm, Identifier::fromString(vm, "direction"), layoutString);
     781    return result;
     782}
     783
     784JSObject* IntlLocale::weekInfo(JSGlobalObject* globalObject)
     785{
     786    VM& vm = globalObject->vm();
     787    auto scope = DECLARE_THROW_SCOPE(vm);
     788
     789    UErrorCode status = U_ZERO_ERROR;
     790    auto calendar = std::unique_ptr<UCalendar, ICUDeleter<ucal_close>>(ucal_open(nullptr, 0, m_localeID.data(), UCAL_DEFAULT, &status));
     791    if (!U_SUCCESS(status)) {
     792        throwTypeError(globalObject, scope, "invalid locale"_s);
     793        return nullptr;
     794    }
     795
     796    int32_t firstDayOfWeek = ucal_getAttribute(calendar.get(), UCAL_FIRST_DAY_OF_WEEK);
     797    int32_t minimalDays = ucal_getAttribute(calendar.get(), UCAL_MINIMAL_DAYS_IN_FIRST_WEEK);
     798
     799    auto canonicalizeDayOfWeekType = [](UCalendarWeekdayType type) {
     800        switch (type) {
     801        // UCAL_WEEKEND_ONSET is a day that starts as a weekday and transitions to the weekend. It means this is WeekDay.
     802        case UCAL_WEEKEND_ONSET:
     803        case UCAL_WEEKDAY:
     804            return UCAL_WEEKDAY;
     805        // UCAL_WEEKEND_CEASE is a day that starts as the weekend and transitions to a weekday. It means this is WeekEnd.
     806        case UCAL_WEEKEND_CEASE:
     807        case UCAL_WEEKEND:
     808            return UCAL_WEEKEND;
     809        default:
     810            return UCAL_WEEKEND;
     811        }
     812    };
     813
     814    static_assert(UCAL_SUNDAY == 1);
     815    static_assert(UCAL_SATURDAY == 7);
     816    UCalendarWeekdayType previous = canonicalizeDayOfWeekType(ucal_getDayOfWeekType(calendar.get(), UCAL_SATURDAY, &status));
     817    if (!U_SUCCESS(status)) {
     818        throwTypeError(globalObject, scope, "invalid locale"_s);
     819        return nullptr;
     820    }
     821
     822    int32_t weekendStart = 0;
     823    int32_t weekendEnd = 0;
     824    for (int32_t day = UCAL_SUNDAY; day <= UCAL_SATURDAY; ++day) {
     825        UCalendarWeekdayType type = canonicalizeDayOfWeekType(ucal_getDayOfWeekType(calendar.get(), static_cast<UCalendarDaysOfWeek>(day), &status));
     826        if (!U_SUCCESS(status)) {
     827            throwTypeError(globalObject, scope, "invalid locale"_s);
     828            return nullptr;
     829        }
     830        if (previous != type) {
     831            switch (type) {
     832            case UCAL_WEEKDAY: // WeekEnd => WeekDay
     833                if (day == UCAL_SUNDAY)
     834                    weekendEnd = UCAL_SATURDAY;
     835                else
     836                    weekendEnd = day - 1;
     837                break;
     838            case UCAL_WEEKEND: // WeekDay => WeekEnd
     839                weekendStart = day;
     840                break;
     841            default:
     842                ASSERT_NOT_REACHED();
     843                break;
     844            }
     845        }
     846        previous = type;
     847    }
     848
     849    auto convertUCalendarDaysOfWeekToMondayBasedDay = [](int32_t day) -> int32_t {
     850        // Convert from
     851        //     Sunday => 1
     852        //     Saturday => 7
     853        // to
     854        //     Monday => 1
     855        //     Sunday => 7
     856        if (day == UCAL_SUNDAY)
     857            return 7;
     858        return day - 1;
     859    };
     860
     861    JSObject* result = constructEmptyObject(globalObject);
     862    result->putDirect(vm, Identifier::fromString(vm, "firstDay"), jsNumber(convertUCalendarDaysOfWeekToMondayBasedDay(firstDayOfWeek)));
     863    result->putDirect(vm, Identifier::fromString(vm, "weekendStart"), jsNumber(convertUCalendarDaysOfWeekToMondayBasedDay(weekendStart)));
     864    result->putDirect(vm, Identifier::fromString(vm, "weekendEnd"), jsNumber(convertUCalendarDaysOfWeekToMondayBasedDay(weekendEnd)));
     865    result->putDirect(vm, Identifier::fromString(vm, "minimalDays"), jsNumber(minimalDays));
     866    return result;
     867}
     868
    535869} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/IntlLocale.h

    r278253 r281374  
    7070    TriState numeric();
    7171
     72    JSArray* calendars(JSGlobalObject*);
     73    JSArray* collations(JSGlobalObject*);
     74    JSArray* hourCycles(JSGlobalObject*);
     75    JSArray* numberingSystems(JSGlobalObject*);
     76    JSValue timeZones(JSGlobalObject*);
     77    JSObject* textInfo(JSGlobalObject*);
     78    JSObject* weekInfo(JSGlobalObject*);
     79
    7280private:
    7381    IntlLocale(VM&, Structure*);
  • trunk/Source/JavaScriptCore/runtime/IntlLocalePrototype.cpp

    r280256 r281374  
    3737static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterBaseName);
    3838static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterCalendar);
     39static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterCalendars);
    3940static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterCaseFirst);
    4041static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterCollation);
     42static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterCollations);
    4143static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterHourCycle);
     44static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterHourCycles);
    4245static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterNumeric);
    4346static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterNumberingSystem);
     47static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterNumberingSystems);
    4448static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterLanguage);
    4549static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterScript);
    4650static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterRegion);
     51static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterTimeZones);
     52static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterTextInfo);
     53static JSC_DECLARE_CUSTOM_GETTER(IntlLocalePrototypeGetterWeekInfo);
    4754
    4855}
     
    6168  baseName         IntlLocalePrototypeGetterBaseName         DontEnum|ReadOnly|CustomAccessor
    6269  calendar         IntlLocalePrototypeGetterCalendar         DontEnum|ReadOnly|CustomAccessor
     70  calendars        IntlLocalePrototypeGetterCalendars        DontEnum|ReadOnly|CustomAccessor
    6371  caseFirst        IntlLocalePrototypeGetterCaseFirst        DontEnum|ReadOnly|CustomAccessor
    6472  collation        IntlLocalePrototypeGetterCollation        DontEnum|ReadOnly|CustomAccessor
     73  collations       IntlLocalePrototypeGetterCollations       DontEnum|ReadOnly|CustomAccessor
    6574  hourCycle        IntlLocalePrototypeGetterHourCycle        DontEnum|ReadOnly|CustomAccessor
     75  hourCycles       IntlLocalePrototypeGetterHourCycles       DontEnum|ReadOnly|CustomAccessor
    6676  numeric          IntlLocalePrototypeGetterNumeric          DontEnum|ReadOnly|CustomAccessor
    6777  numberingSystem  IntlLocalePrototypeGetterNumberingSystem  DontEnum|ReadOnly|CustomAccessor
     78  numberingSystems IntlLocalePrototypeGetterNumberingSystems DontEnum|ReadOnly|CustomAccessor
    6879  language         IntlLocalePrototypeGetterLanguage         DontEnum|ReadOnly|CustomAccessor
    6980  script           IntlLocalePrototypeGetterScript           DontEnum|ReadOnly|CustomAccessor
    7081  region           IntlLocalePrototypeGetterRegion           DontEnum|ReadOnly|CustomAccessor
     82  timeZones        IntlLocalePrototypeGetterTimeZones        DontEnum|ReadOnly|CustomAccessor
     83  textInfo         IntlLocalePrototypeGetterTextInfo         DontEnum|ReadOnly|CustomAccessor
     84  weekInfo         IntlLocalePrototypeGetterWeekInfo         DontEnum|ReadOnly|CustomAccessor
    7185@end
    7286*/
     
    170184}
    171185
     186// https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.calendars
     187JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterCalendars, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     188{
     189    VM& vm = globalObject->vm();
     190    auto scope = DECLARE_THROW_SCOPE(vm);
     191
     192    auto* locale = jsDynamicCast<IntlLocale*>(vm, JSValue::decode(thisValue));
     193    if (!locale)
     194        return throwVMTypeError(globalObject, scope, "Intl.Locale.prototype.calendars called on value that's not an object initialized as a Locale"_s);
     195
     196    RELEASE_AND_RETURN(scope, JSValue::encode(locale->calendars(globalObject)));
     197}
     198
    172199// https://tc39.es/ecma402/#sec-Intl.Locale.prototype.caseFirst
    173200JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterCaseFirst, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     
    198225}
    199226
     227// https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.collations
     228JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterCollations, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     229{
     230    VM& vm = globalObject->vm();
     231    auto scope = DECLARE_THROW_SCOPE(vm);
     232
     233    auto* locale = jsDynamicCast<IntlLocale*>(vm, JSValue::decode(thisValue));
     234    if (!locale)
     235        return throwVMTypeError(globalObject, scope, "Intl.Locale.prototype.collations called on value that's not an object initialized as a Locale"_s);
     236
     237    RELEASE_AND_RETURN(scope, JSValue::encode(locale->collations(globalObject)));
     238}
     239
    200240// https://tc39.es/ecma402/#sec-Intl.Locale.prototype.hourCycle
    201241JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterHourCycle, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     
    212252}
    213253
     254// https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.hourcycles
     255JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterHourCycles, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     256{
     257    VM& vm = globalObject->vm();
     258    auto scope = DECLARE_THROW_SCOPE(vm);
     259
     260    auto* locale = jsDynamicCast<IntlLocale*>(vm, JSValue::decode(thisValue));
     261    if (!locale)
     262        return throwVMTypeError(globalObject, scope, "Intl.Locale.prototype.hourCycles called on value that's not an object initialized as a Locale"_s);
     263
     264    RELEASE_AND_RETURN(scope, JSValue::encode(locale->hourCycles(globalObject)));
     265}
     266
    214267// https://tc39.es/ecma402/#sec-Intl.Locale.prototype.numeric
    215268JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterNumeric, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     
    239292}
    240293
     294// https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.numberingSystems
     295JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterNumberingSystems, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     296{
     297    VM& vm = globalObject->vm();
     298    auto scope = DECLARE_THROW_SCOPE(vm);
     299
     300    auto* locale = jsDynamicCast<IntlLocale*>(vm, JSValue::decode(thisValue));
     301    if (!locale)
     302        return throwVMTypeError(globalObject, scope, "Intl.Locale.prototype.numberingSystems called on value that's not an object initialized as a Locale"_s);
     303
     304    RELEASE_AND_RETURN(scope, JSValue::encode(locale->numberingSystems(globalObject)));
     305}
     306
    241307// https://tc39.es/ecma402/#sec-Intl.Locale.prototype.language
    242308JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterLanguage, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     
    281347}
    282348
     349// https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.timezones
     350JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterTimeZones, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     351{
     352    VM& vm = globalObject->vm();
     353    auto scope = DECLARE_THROW_SCOPE(vm);
     354
     355    auto* locale = jsDynamicCast<IntlLocale*>(vm, JSValue::decode(thisValue));
     356    if (!locale)
     357        return throwVMTypeError(globalObject, scope, "Intl.Locale.prototype.timeZones called on value that's not an object initialized as a Locale"_s);
     358
     359    RELEASE_AND_RETURN(scope, JSValue::encode(locale->timeZones(globalObject)));
     360}
     361
     362// https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.textInfo
     363JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterTextInfo, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     364{
     365    VM& vm = globalObject->vm();
     366    auto scope = DECLARE_THROW_SCOPE(vm);
     367
     368    auto* locale = jsDynamicCast<IntlLocale*>(vm, JSValue::decode(thisValue));
     369    if (!locale)
     370        return throwVMTypeError(globalObject, scope, "Intl.Locale.prototype.textInfo called on value that's not an object initialized as a Locale"_s);
     371
     372    RELEASE_AND_RETURN(scope, JSValue::encode(locale->textInfo(globalObject)));
     373}
     374
     375// https://tc39.es/proposal-intl-locale-info/#sec-Intl.Locale.prototype.weekInfo
     376JSC_DEFINE_CUSTOM_GETTER(IntlLocalePrototypeGetterWeekInfo, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
     377{
     378    VM& vm = globalObject->vm();
     379    auto scope = DECLARE_THROW_SCOPE(vm);
     380
     381    auto* locale = jsDynamicCast<IntlLocale*>(vm, JSValue::decode(thisValue));
     382    if (!locale)
     383        return throwVMTypeError(globalObject, scope, "Intl.Locale.prototype.weekInfo called on value that's not an object initialized as a Locale"_s);
     384
     385    RELEASE_AND_RETURN(scope, JSValue::encode(locale->weekInfo(globalObject)));
     386}
     387
    283388} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/IntlObject.cpp

    r278253 r281374  
    14591459}
    14601460
     1461std::optional<String> mapICUCalendarKeywordToBCP47(const String& calendar)
     1462{
     1463    if (calendar == "gregorian"_s)
     1464        return "gregory"_s;
     1465    if (calendar == "islamic-civil"_s)
     1466        return "islamicc"_s;
     1467    if (calendar == "ethiopic-amete-alem"_s)
     1468        return "ethioaa"_s;
     1469    return std::nullopt;
     1470}
     1471
     1472std::optional<String> mapICUCollationKeywordToBCP47(const String& collation)
     1473{
     1474    // Map keyword values to BCP 47 equivalents.
     1475    if (collation == "dictionary"_s)
     1476        return "dict"_s;
     1477    if (collation == "gb2312han"_s)
     1478        return "gb2312"_s;
     1479    if (collation == "phonebook"_s)
     1480        return "phonebk"_s;
     1481    if (collation == "traditional"_s)
     1482        return "trad"_s;
     1483    return std::nullopt;
     1484}
     1485
    14611486JSC_DEFINE_HOST_FUNCTION(intlObjectFuncGetCanonicalLocales, (JSGlobalObject* globalObject, CallFrame* callFrame))
    14621487{
  • trunk/Source/JavaScriptCore/runtime/IntlObject.h

    r278253 r281374  
    137137};
    138138
     139std::optional<String> mapICUCollationKeywordToBCP47(const String&);
     140std::optional<String> mapICUCalendarKeywordToBCP47(const String&);
     141
    139142} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.