WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-214795-20210821163249.patch (text/plain), 38.54 KB, created by
Yusuke Suzuki
on 2021-08-21 16:32:50 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2021-08-21 16:32:50 PDT
Size:
38.54 KB
patch
obsolete
>Subversion Revision: 281379 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 6c30e990140e4628e69e262acf0e2f54db881533..568ab916b61f859ee89c51dcff4c17b9a9a5ef71 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,36 @@ >+2021-08-21 Yusuke Suzuki <ysuzuki@apple.com> >+ >+ [JSC] Add Intl Enumeration APIs >+ https://bugs.webkit.org/show_bug.cgi?id=214795 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch implements Intl enumeration API[1] which is in stage-3. >+ Supported keys are, "calendar", "collation", "currency", "numberingSystem", "timeZone", and "unit". >+ >+ [1]: https://github.com/tc39/proposal-intl-enumeration >+ >+ * runtime/IntlDateTimeFormat.cpp: >+ (JSC::IntlDateTimeFormat::localeData): >+ * runtime/IntlLocale.cpp: >+ (JSC::createArrayFromStringVector): Deleted. >+ * runtime/IntlNumberFormat.cpp: >+ (JSC::sanctionedSimpleUnitIdentifier): >+ * runtime/IntlObject.cpp: >+ (JSC::IntlObject::finishCreation): >+ (JSC::mapICUCalendarKeywordToBCP47): >+ (JSC::availableCalendars): >+ (JSC::availableCollations): >+ (JSC::availableCurrencies): >+ (JSC::availableNumberingSystems): >+ (JSC::canonicalizeTimeZoneNameFromICUTimeZone): >+ (JSC::availableTimeZones): >+ (JSC::availableUnits): >+ (JSC::JSC_DEFINE_HOST_FUNCTION): >+ (JSC::createArrayFromStringVector): >+ * runtime/IntlObject.h: >+ * runtime/OptionsList.h: >+ > 2021-08-21 Yusuke Suzuki <ysuzuki@apple.com> > > [JSC] Intl.DisplayNames v2 >diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog >index fe45041a8790ac2f6121fccb20feee539462eed0..ed28f36c3ec352e9c0030fd44c5df8a9ee82cb36 100644 >--- a/Source/WTF/ChangeLog >+++ b/Source/WTF/ChangeLog >@@ -1,3 +1,14 @@ >+2021-08-21 Yusuke Suzuki <ysuzuki@apple.com> >+ >+ [JSC] Add Intl Enumeration APIs >+ https://bugs.webkit.org/show_bug.cgi?id=214795 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * wtf/text/StringImpl.cpp: >+ (WTF::StringImpl::createFromLiteral): >+ * wtf/text/StringImpl.h: >+ > 2021-08-20 Mark Lam <mark.lam@apple.com> > > Make ptrTagName and tagForPtr WTF_EXPORT_PRIVATE. >diff --git a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp >index 18270e32680c81d771efcf068821e050e4c19580..41c75f2a54189f3517f3c3daef5e2affcbcbc308 100644 >--- a/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp >+++ b/Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp >@@ -165,6 +165,9 @@ Vector<String> IntlDateTimeFormat::localeData(const String& locale, RelevantExte > ASSERT(U_SUCCESS(status)); > String calendar = String(availableName, nameLength); > keyLocaleData.append(calendar); >+ // Adding "islamicc" candidate for backward compatibility. >+ if (calendar == "islamic-civil"_s) >+ keyLocaleData.append("islamicc"_s); > if (auto mapped = mapICUCalendarKeywordToBCP47(calendar)) > keyLocaleData.append(WTFMove(mapped.value())); > } >diff --git a/Source/JavaScriptCore/runtime/IntlLocale.cpp b/Source/JavaScriptCore/runtime/IntlLocale.cpp >index 9a059078389febb85a2f33c4af47b425c3dc4204..c3b26dd82b540a1af47027f4459d160452d33f5d 100644 >--- a/Source/JavaScriptCore/runtime/IntlLocale.cpp >+++ b/Source/JavaScriptCore/runtime/IntlLocale.cpp >@@ -537,23 +537,6 @@ TriState IntlLocale::numeric() > return m_numeric; > } > >-static inline JSArray* createArrayFromStringVector(JSGlobalObject* globalObject, Vector<String, 1>&& elements) >-{ >- VM& vm = globalObject->vm(); >- auto scope = DECLARE_THROW_SCOPE(vm); >- >- JSArray* result = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), elements.size()); >- if (!result) { >- throwOutOfMemoryError(globalObject, scope); >- return nullptr; >- } >- for (unsigned index = 0; index < elements.size(); ++index) { >- result->putDirectIndex(globalObject, index, jsString(vm, WTFMove(elements[index]))); >- RETURN_IF_EXCEPTION(scope, { }); >- } >- return result; >-} >- > JSArray* IntlLocale::calendars(JSGlobalObject* globalObject) > { > VM& vm = globalObject->vm(); >diff --git a/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp b/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp >index 3d99fb91a9acbab65c081f331d3158703fb9f740..fc3237032022b4c6d67dd81559ec335b56bd0dff 100644 >--- a/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp >+++ b/Source/JavaScriptCore/runtime/IntlNumberFormat.cpp >@@ -151,59 +151,8 @@ static unsigned computeCurrencyDigits(const String& currency) > return 2; > } > >-// Create MeasureUnit like ICU4J. >-struct MeasureUnit { >- ASCIILiteral type; >- ASCIILiteral subType; >-}; >- > static std::optional<MeasureUnit> sanctionedSimpleUnitIdentifier(StringView unitIdentifier) > { >- static constexpr MeasureUnit simpleUnits[] = { >- { "area"_s, "acre"_s }, >- { "digital"_s, "bit"_s }, >- { "digital"_s, "byte"_s }, >- { "temperature"_s, "celsius"_s }, >- { "length"_s, "centimeter"_s }, >- { "duration"_s, "day"_s }, >- { "angle"_s, "degree"_s }, >- { "temperature"_s, "fahrenheit"_s }, >- { "volume"_s, "fluid-ounce"_s }, >- { "length"_s, "foot"_s }, >- { "volume"_s, "gallon"_s }, >- { "digital"_s, "gigabit"_s }, >- { "digital"_s, "gigabyte"_s }, >- { "mass"_s, "gram"_s }, >- { "area"_s, "hectare"_s }, >- { "duration"_s, "hour"_s }, >- { "length"_s, "inch"_s }, >- { "digital"_s, "kilobit"_s }, >- { "digital"_s, "kilobyte"_s }, >- { "mass"_s, "kilogram"_s }, >- { "length"_s, "kilometer"_s }, >- { "volume"_s, "liter"_s }, >- { "digital"_s, "megabit"_s }, >- { "digital"_s, "megabyte"_s }, >- { "length"_s, "meter"_s }, >- { "length"_s, "mile"_s }, >- { "length"_s, "mile-scandinavian"_s }, >- { "volume"_s, "milliliter"_s }, >- { "length"_s, "millimeter"_s }, >- { "duration"_s, "millisecond"_s }, >- { "duration"_s, "minute"_s }, >- { "duration"_s, "month"_s }, >- { "mass"_s, "ounce"_s }, >- { "concentr"_s, "percent"_s }, >- { "digital"_s, "petabyte"_s }, >- { "mass"_s, "pound"_s }, >- { "duration"_s, "second"_s }, >- { "mass"_s, "stone"_s }, >- { "digital"_s, "terabit"_s }, >- { "digital"_s, "terabyte"_s }, >- { "duration"_s, "week"_s }, >- { "length"_s, "yard"_s }, >- { "duration"_s, "year"_s }, >- }; > ASSERT( > std::is_sorted(std::begin(simpleUnits), std::end(simpleUnits), > [](const MeasureUnit& a, const MeasureUnit& b) { >diff --git a/Source/JavaScriptCore/runtime/IntlObject.cpp b/Source/JavaScriptCore/runtime/IntlObject.cpp >index 03c9d7986f95a071b69538933b81d74634113c87..d5c26afd5b49bb4b6fb500c7c07ad86bd7c5f90a 100644 >--- a/Source/JavaScriptCore/runtime/IntlObject.cpp >+++ b/Source/JavaScriptCore/runtime/IntlObject.cpp >@@ -58,6 +58,7 @@ > #include "JSCInlines.h" > #include "Options.h" > #include <unicode/ubrk.h> >+#include <unicode/ucal.h> > #include <unicode/ucol.h> > #include <unicode/ufieldpositer.h> > #include <unicode/uloc.h> >@@ -75,6 +76,7 @@ namespace JSC { > STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(IntlObject); > > static JSC_DECLARE_HOST_FUNCTION(intlObjectFuncGetCanonicalLocales); >+static JSC_DECLARE_HOST_FUNCTION(intlObjectFuncSupportedValuesOf); > > static JSValue createCollatorConstructor(VM& vm, JSObject* object) > { >@@ -172,6 +174,52 @@ void UFieldPositionIteratorDeleter::operator()(UFieldPositionIterator* iterator) > ufieldpositer_close(iterator); > } > >+const MeasureUnit simpleUnits[43] = { >+ { "area"_s, "acre"_s }, >+ { "digital"_s, "bit"_s }, >+ { "digital"_s, "byte"_s }, >+ { "temperature"_s, "celsius"_s }, >+ { "length"_s, "centimeter"_s }, >+ { "duration"_s, "day"_s }, >+ { "angle"_s, "degree"_s }, >+ { "temperature"_s, "fahrenheit"_s }, >+ { "volume"_s, "fluid-ounce"_s }, >+ { "length"_s, "foot"_s }, >+ { "volume"_s, "gallon"_s }, >+ { "digital"_s, "gigabit"_s }, >+ { "digital"_s, "gigabyte"_s }, >+ { "mass"_s, "gram"_s }, >+ { "area"_s, "hectare"_s }, >+ { "duration"_s, "hour"_s }, >+ { "length"_s, "inch"_s }, >+ { "digital"_s, "kilobit"_s }, >+ { "digital"_s, "kilobyte"_s }, >+ { "mass"_s, "kilogram"_s }, >+ { "length"_s, "kilometer"_s }, >+ { "volume"_s, "liter"_s }, >+ { "digital"_s, "megabit"_s }, >+ { "digital"_s, "megabyte"_s }, >+ { "length"_s, "meter"_s }, >+ { "length"_s, "mile"_s }, >+ { "length"_s, "mile-scandinavian"_s }, >+ { "volume"_s, "milliliter"_s }, >+ { "length"_s, "millimeter"_s }, >+ { "duration"_s, "millisecond"_s }, >+ { "duration"_s, "minute"_s }, >+ { "duration"_s, "month"_s }, >+ { "mass"_s, "ounce"_s }, >+ { "concentr"_s, "percent"_s }, >+ { "digital"_s, "petabyte"_s }, >+ { "mass"_s, "pound"_s }, >+ { "duration"_s, "second"_s }, >+ { "mass"_s, "stone"_s }, >+ { "digital"_s, "terabit"_s }, >+ { "digital"_s, "terabyte"_s }, >+ { "duration"_s, "week"_s }, >+ { "length"_s, "yard"_s }, >+ { "duration"_s, "year"_s }, >+}; >+ > IntlObject::IntlObject(VM& vm, Structure* structure) > : Base(vm, structure) > { >@@ -184,7 +232,7 @@ IntlObject* IntlObject::create(VM& vm, JSGlobalObject* globalObject, Structure* > return object; > } > >-void IntlObject::finishCreation(VM& vm, JSGlobalObject*) >+void IntlObject::finishCreation(VM& vm, JSGlobalObject* globalObject) > { > Base::finishCreation(vm); > ASSERT(inherits(vm, info())); >@@ -199,6 +247,8 @@ void IntlObject::finishCreation(VM& vm, JSGlobalObject*) > #else > UNUSED_PARAM(&createListFormatConstructor); > #endif >+ if (Options::useIntlEnumeration()) >+ JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("supportedValuesOf", intlObjectFuncSupportedValuesOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); > } > > Structure* IntlObject::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) >@@ -1468,8 +1518,8 @@ std::optional<String> mapICUCalendarKeywordToBCP47(const String& calendar) > { > if (calendar == "gregorian"_s) > return "gregory"_s; >- if (calendar == "islamic-civil"_s) >- return "islamicc"_s; >+ // islamicc is deprecated in BCP47, and islamic-civil is preferred. >+ // https://github.com/unicode-org/cldr/blob/master/common/bcp47/calendar.xml > if (calendar == "ethiopic-amete-alem"_s) > return "ethioaa"_s; > return std::nullopt; >@@ -1524,4 +1574,311 @@ JSC_DEFINE_HOST_FUNCTION(intlObjectFuncGetCanonicalLocales, (JSGlobalObject* glo > return JSValue::encode(localeArray); > } > >+// https://tc39.es/proposal-intl-enumeration/#sec-availablecalendars >+static JSArray* availableCalendars(JSGlobalObject* globalObject) >+{ >+ VM& vm = globalObject->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ UErrorCode status = U_ZERO_ERROR; >+ auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucal_getKeywordValuesForLocale("calendars", "und", false, &status)); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available calendars"_s); >+ return { }; >+ } >+ >+ int32_t count = uenum_count(enumeration.get(), &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available calendars"_s); >+ return { }; >+ } >+ >+ Vector<String, 1> elements; >+ elements.reserveInitialCapacity(count); >+ for (int32_t index = 0; index < count; ++index) { >+ int32_t length = 0; >+ const char* pointer = uenum_next(enumeration.get(), &length, &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available calendars"_s); >+ return { }; >+ } >+ String calendar(pointer, length); >+ if (auto mapped = mapICUCalendarKeywordToBCP47(calendar)) >+ elements.append(WTFMove(mapped.value())); >+ else >+ elements.append(WTFMove(calendar)); >+ } >+ >+ // The AvailableCalendars abstract operation returns a List, ordered as if an Array of the same >+ // values had been sorted using %Array.prototype.sort% using undefined as comparefn >+ std::sort(elements.begin(), elements.end(), >+ [](const String& a, const String& b) { >+ return WTF::codePointCompare(a, b) < 0; >+ }); >+ >+ return createArrayFromStringVector(globalObject, WTFMove(elements)); >+} >+ >+// https://tc39.es/proposal-intl-enumeration/#sec-availablecollations >+static JSArray* availableCollations(JSGlobalObject* globalObject) >+{ >+ VM& vm = globalObject->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ UErrorCode status = U_ZERO_ERROR; >+ auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucol_getKeywordValues("collation", &status)); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available collations"_s); >+ return { }; >+ } >+ >+ int32_t count = uenum_count(enumeration.get(), &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available collations"_s); >+ return { }; >+ } >+ >+ Vector<String, 1> elements; >+ elements.reserveInitialCapacity(count); >+ for (int32_t index = 0; index < count; ++index) { >+ int32_t length = 0; >+ const char* pointer = uenum_next(enumeration.get(), &length, &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available collations"_s); >+ return { }; >+ } >+ String collation(pointer, length); >+ if (collation == "standard"_s || collation == "search"_s) >+ continue; >+ if (auto mapped = mapICUCollationKeywordToBCP47(collation)) >+ elements.append(WTFMove(mapped.value())); >+ else >+ elements.append(WTFMove(collation)); >+ } >+ >+ // The AvailableCollations abstract operation returns a List, ordered as if an Array of the same >+ // values had been sorted using %Array.prototype.sort% using undefined as comparefn >+ std::sort(elements.begin(), elements.end(), >+ [](const String& a, const String& b) { >+ return WTF::codePointCompare(a, b) < 0; >+ }); >+ >+ return createArrayFromStringVector(globalObject, WTFMove(elements)); >+} >+ >+// https://tc39.es/proposal-intl-enumeration/#sec-availablecurrencies >+static JSArray* availableCurrencies(JSGlobalObject* globalObject) >+{ >+ VM& vm = globalObject->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ UErrorCode status = U_ZERO_ERROR; >+ auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucurr_openISOCurrencies(UCURR_COMMON | UCURR_NON_DEPRECATED, &status)); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available currencies"_s); >+ return { }; >+ } >+ >+ int32_t count = uenum_count(enumeration.get(), &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available currencies"_s); >+ return { }; >+ } >+ >+ Vector<String, 1> elements; >+ elements.reserveInitialCapacity(count); >+ for (int32_t index = 0; index < count; ++index) { >+ int32_t length = 0; >+ const char* currency = uenum_next(enumeration.get(), &length, &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available currencies"_s); >+ return { }; >+ } >+ elements.constructAndAppend(currency, length); >+ } >+ >+ // The AvailableCurrencies abstract operation returns a List, ordered as if an Array of the same >+ // values had been sorted using %Array.prototype.sort% using undefined as comparefn >+ std::sort(elements.begin(), elements.end(), >+ [](const String& a, const String& b) { >+ return WTF::codePointCompare(a, b) < 0; >+ }); >+ >+ return createArrayFromStringVector(globalObject, WTFMove(elements)); >+} >+ >+// https://tc39.es/proposal-intl-enumeration/#sec-availablenumberingsystems >+static JSArray* availableNumberingSystems(JSGlobalObject* globalObject) >+{ >+ VM& vm = globalObject->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ UErrorCode status = U_ZERO_ERROR; >+ auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(unumsys_openAvailableNames(&status)); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available numbering systems"_s); >+ return { }; >+ } >+ >+ int32_t count = uenum_count(enumeration.get(), &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available numbering systems"_s); >+ return { }; >+ } >+ >+ Vector<String, 1> elements; >+ elements.reserveInitialCapacity(count); >+ for (int32_t index = 0; index < count; ++index) { >+ int32_t length = 0; >+ const char* numberingSystem = uenum_next(enumeration.get(), &length, &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available numbering systems"_s); >+ return { }; >+ } >+ elements.constructAndAppend(numberingSystem, length); >+ } >+ >+ // The AvailableNumberingSystems abstract operation returns a List, ordered as if an Array of the same >+ // values had been sorted using %Array.prototype.sort% using undefined as comparefn >+ std::sort(elements.begin(), elements.end(), >+ [](const String& a, const String& b) { >+ return WTF::codePointCompare(a, b) < 0; >+ }); >+ >+ return createArrayFromStringVector(globalObject, WTFMove(elements)); >+} >+ >+// https://tc39.es/proposal-intl-enumeration/#sec-canonicalizetimezonename >+static std::optional<String> canonicalizeTimeZoneNameFromICUTimeZone(const String& timeZoneName) >+{ >+ // Some time zone names are included in ICU, but they are not included in the IANA Time Zone Database. >+ // We need to filter them out. >+ if (timeZoneName.startsWith("SystemV/")) >+ return std::nullopt; >+ if (timeZoneName.startsWith("Etc/")) >+ return std::nullopt; >+ // IANA time zone names include '/'. Some of them are not including, but it is in backward links. >+ // And ICU already resolved these backward links. >+ if (!timeZoneName.contains('/')) >+ return std::nullopt; >+ >+ return timeZoneName; >+} >+ >+// https://tc39.es/proposal-intl-enumeration/#sec-availabletimezones >+static JSArray* availableTimeZones(JSGlobalObject* globalObject) >+{ >+ VM& vm = globalObject->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ UErrorCode status = U_ZERO_ERROR; >+ auto enumeration = std::unique_ptr<UEnumeration, ICUDeleter<uenum_close>>(ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, nullptr, nullptr, &status)); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available timezones"_s); >+ return { }; >+ } >+ >+ int32_t count = uenum_count(enumeration.get(), &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available timezones"_s); >+ return { }; >+ } >+ >+ Vector<String, 1> elements; >+ elements.reserveInitialCapacity(count); >+ for (int32_t index = 0; index < count; ++index) { >+ int32_t length = 0; >+ const char* pointer = uenum_next(enumeration.get(), &length, &status); >+ if (U_FAILURE(status)) { >+ throwTypeError(globalObject, scope, "failed to enumerate available timezones"_s); >+ return { }; >+ } >+ String timeZone(pointer, length); >+ if (auto mapped = canonicalizeTimeZoneNameFromICUTimeZone(timeZone)) >+ elements.append(WTFMove(mapped.value())); >+ } >+ >+ // 4. Sort result in order as if an Array of the same values had been sorted using %Array.prototype.sort% using undefined as comparefn. >+ std::sort(elements.begin(), elements.end(), >+ [](const String& a, const String& b) { >+ return WTF::codePointCompare(a, b) < 0; >+ }); >+ >+ return createArrayFromStringVector(globalObject, WTFMove(elements)); >+} >+ >+// https://tc39.es/proposal-intl-enumeration/#sec-availableunits >+static JSArray* availableUnits(JSGlobalObject* globalObject) >+{ >+ VM& vm = globalObject->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ JSArray* result = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), std::size(simpleUnits)); >+ if (!result) { >+ throwOutOfMemoryError(globalObject, scope); >+ return { }; >+ } >+ >+ ASSERT( >+ std::is_sorted(std::begin(simpleUnits), std::end(simpleUnits), >+ [](const MeasureUnit& a, const MeasureUnit& b) { >+ return WTF::codePointCompare(StringView(a.subType), StringView(b.subType)) < 0; >+ })); >+ >+ int32_t index = 0; >+ for (const MeasureUnit& unit : simpleUnits) { >+ result->putDirectIndex(globalObject, index++, jsString(vm, StringImpl::createFromLiteral(unit.subType))); >+ RETURN_IF_EXCEPTION(scope, { }); >+ } >+ return result; >+} >+ >+// https://tc39.es/proposal-intl-enumeration/#sec-intl.supportedvaluesof >+JSC_DEFINE_HOST_FUNCTION(intlObjectFuncSupportedValuesOf, (JSGlobalObject* globalObject, CallFrame* callFrame)) >+{ >+ VM& vm = globalObject->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ String key = callFrame->argument(0).toWTFString(globalObject); >+ RETURN_IF_EXCEPTION(scope, { }); >+ >+ if (key == "calendar"_s) >+ RELEASE_AND_RETURN(scope, JSValue::encode(availableCalendars(globalObject))); >+ >+ if (key == "collation"_s) >+ RELEASE_AND_RETURN(scope, JSValue::encode(availableCollations(globalObject))); >+ >+ if (key == "currency"_s) >+ RELEASE_AND_RETURN(scope, JSValue::encode(availableCurrencies(globalObject))); >+ >+ if (key == "numberingSystem"_s) >+ RELEASE_AND_RETURN(scope, JSValue::encode(availableNumberingSystems(globalObject))); >+ >+ if (key == "timeZone"_s) >+ RELEASE_AND_RETURN(scope, JSValue::encode(availableTimeZones(globalObject))); >+ >+ if (key == "unit"_s) >+ RELEASE_AND_RETURN(scope, JSValue::encode(availableUnits(globalObject))); >+ >+ throwRangeError(globalObject, scope, "Unknown key for Intl.supportedValuesOf"_s); >+ return { }; >+} >+ >+JSArray* createArrayFromStringVector(JSGlobalObject* globalObject, Vector<String, 1>&& elements) >+{ >+ VM& vm = globalObject->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ JSArray* result = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), elements.size()); >+ if (!result) { >+ throwOutOfMemoryError(globalObject, scope); >+ return nullptr; >+ } >+ for (unsigned index = 0; index < elements.size(); ++index) { >+ result->putDirectIndex(globalObject, index, jsString(vm, WTFMove(elements[index]))); >+ RETURN_IF_EXCEPTION(scope, { }); >+ } >+ return result; >+} >+ > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/IntlObject.h b/Source/JavaScriptCore/runtime/IntlObject.h >index cc01f6cadd4105fe5388ca7879e0041a95f051cc..dc696d65fa5c636322a6c514f8b00784def2fc6b 100644 >--- a/Source/JavaScriptCore/runtime/IntlObject.h >+++ b/Source/JavaScriptCore/runtime/IntlObject.h >@@ -60,6 +60,13 @@ JSC_INTL_RELEVANT_EXTENSION_KEYS(JSC_DECLARE_INTL_RELEVANT_EXTENSION_KEYS) > static constexpr uint8_t numberOfRelevantExtensionKeys = 0 JSC_INTL_RELEVANT_EXTENSION_KEYS(JSC_COUNT_INTL_RELEVANT_EXTENSION_KEYS); > #undef JSC_COUNT_INTL_RELEVANT_EXTENSION_KEYS > >+struct MeasureUnit { >+ ASCIILiteral type; >+ ASCIILiteral subType; >+}; >+ >+extern JS_EXPORT_PRIVATE const MeasureUnit simpleUnits[43]; >+ > class IntlObject final : public JSNonFinalObject { > public: > using Base = JSNonFinalObject; >@@ -141,4 +148,6 @@ std::optional<String> mapICUCollationKeywordToBCP47(const String&); > std::optional<String> mapICUCalendarKeywordToBCP47(const String&); > std::optional<String> mapBCP47ToICUCalendarKeyword(const String&); > >+JSArray* createArrayFromStringVector(JSGlobalObject*, Vector<String, 1>&&); >+ > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/OptionsList.h b/Source/JavaScriptCore/runtime/OptionsList.h >index a6aabfaa0cc8a1faf031bf625c648c6b26d45608..3700aa40b0d312a8cbd8ace1df10dd7b128daebc 100644 >--- a/Source/JavaScriptCore/runtime/OptionsList.h >+++ b/Source/JavaScriptCore/runtime/OptionsList.h >@@ -544,6 +544,7 @@ bool canUseWebAssemblyFastMemory(); > v(Bool, useWeakRefs, true, Normal, "Expose the WeakRef constructor.") \ > v(Bool, useIntlDateTimeFormatDayPeriod, true, Normal, "Expose the Intl.DateTimeFormat dayPeriod feature.") \ > v(Bool, useIntlDateTimeFormatRangeToParts, true, Normal, "Expose the Intl.DateTimeFormat#formatRangeToParts feature.") \ >+ v(Bool, useIntlEnumeration, true, Normal, "Expose the Intl enumeration APIs.") \ > v(Bool, useAtMethod, true, Normal, "Expose the at() method on Array, %TypedArray%, and String.") \ > v(Bool, useErrorCause, true, Normal, "Allow a cause to be provided when constructing an Error, _NativeError_, or AggregateError.") \ > v(Bool, useSharedArrayBuffer, false, Normal, nullptr) \ >diff --git a/Source/WTF/wtf/text/StringImpl.cpp b/Source/WTF/wtf/text/StringImpl.cpp >index 7d3f34631ac8e7975e9f44873553cef1ed78d03f..74f569882e6d4694983f7190a1770216da26cc87 100644 >--- a/Source/WTF/wtf/text/StringImpl.cpp >+++ b/Source/WTF/wtf/text/StringImpl.cpp >@@ -163,6 +163,11 @@ Ref<StringImpl> StringImpl::createFromLiteral(const char* characters) > return createFromLiteral(characters, strlen(characters)); > } > >+Ref<StringImpl> StringImpl::createFromLiteral(ASCIILiteral literal) >+{ >+ return createFromLiteral(literal.characters(), literal.length()); >+} >+ > Ref<StringImpl> StringImpl::createWithoutCopying(const UChar* characters, unsigned length) > { > if (!length) >diff --git a/Source/WTF/wtf/text/StringImpl.h b/Source/WTF/wtf/text/StringImpl.h >index 4203c1c82541a9d87d7b5b0fbb748b16aca5885e..ada9d41b02a8946db731faafb9dec67acafe5dc7 100644 >--- a/Source/WTF/wtf/text/StringImpl.h >+++ b/Source/WTF/wtf/text/StringImpl.h >@@ -33,6 +33,7 @@ > #include <wtf/StdLibExtras.h> > #include <wtf/Vector.h> > #include <wtf/text/ASCIIFastPath.h> >+#include <wtf/text/ASCIILiteral.h> > #include <wtf/text/ConversionMode.h> > #include <wtf/text/StringBuffer.h> > #include <wtf/text/StringCommon.h> >@@ -249,6 +250,7 @@ class StringImpl : private StringImplShape { > // FIXME: Replace calls to these overloads of createFromLiteral to createWithoutCopying instead. > WTF_EXPORT_PRIVATE static Ref<StringImpl> createFromLiteral(const char*, unsigned length); > WTF_EXPORT_PRIVATE static Ref<StringImpl> createFromLiteral(const char*); >+ WTF_EXPORT_PRIVATE static Ref<StringImpl> createFromLiteral(ASCIILiteral); > > WTF_EXPORT_PRIVATE static Ref<StringImpl> createWithoutCopying(const UChar*, unsigned length); > WTF_EXPORT_PRIVATE static Ref<StringImpl> createWithoutCopying(const LChar*, unsigned length); >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index 0c3e7748c2359701ac173ccea1e892eff93d255c..da38a93c2090c83e90764e085c7825c8ad0da9d1 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,14 @@ >+2021-08-21 Yusuke Suzuki <ysuzuki@apple.com> >+ >+ [JSC] Add Intl Enumeration APIs >+ https://bugs.webkit.org/show_bug.cgi?id=214795 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * stress/intl-enumeration.js: Added. >+ (shouldBe): >+ (shouldThrow): >+ > 2021-08-21 Yusuke Suzuki <ysuzuki@apple.com> > > [JSC] Intl.DisplayNames v2 >diff --git a/JSTests/stress/intl-enumeration.js b/JSTests/stress/intl-enumeration.js >new file mode 100644 >index 0000000000000000000000000000000000000000..426b7b0cd336f85f1c4f461f86844230ebb897da >--- /dev/null >+++ b/JSTests/stress/intl-enumeration.js >@@ -0,0 +1,38 @@ >+function shouldBe(actual, expected) { >+ if (actual !== expected) >+ throw new Error(`expected ${expected} but got ${actual}`); >+} >+ >+function shouldThrow(func, errorType) { >+ let error; >+ try { >+ func(); >+ } catch (e) { >+ error = e; >+ } >+ >+ if (!(error instanceof errorType)) >+ throw new Error(`Expected ${errorType.name}!`); >+} >+ >+let calendars = Intl.supportedValuesOf("calendar"); >+shouldBe(JSON.stringify(calendars), `["buddhist","chinese","coptic","dangi","ethioaa","ethiopic","gregory","hebrew","indian","islamic","islamic-civil","islamic-rgsa","islamic-tbla","islamic-umalqura","iso8601","japanese","persian","roc"]`); >+ >+let collations = Intl.supportedValuesOf("collation"); >+shouldBe(JSON.stringify(collations), `["big5han","compat","dict","gb2312","phonebk","phonetic","pinyin","reformed","searchjl","stroke","trad","unihan","zhuyin"]`); >+ >+let currencies = Intl.supportedValuesOf("currency"); >+shouldBe(JSON.stringify(currencies), `["AED","AFN","ALL","AMD","ANG","AOA","ARS","AUD","AWG","AZN","BAM","BBD","BDT","BGN","BHD","BIF","BMD","BND","BOB","BRL","BSD","BTN","BWP","BYN","BZD","CAD","CDF","CHF","CLP","CNY","COP","CRC","CUC","CUP","CVE","CZK","DJF","DKK","DOP","DZD","EGP","ERN","ETB","EUR","FJD","FKP","GBP","GEL","GHS","GIP","GMD","GNF","GTQ","GYD","HKD","HNL","HRK","HTG","HUF","IDR","ILS","INR","IQD","IRR","ISK","JMD","JOD","JPY","KES","KGS","KHR","KMF","KPW","KRW","KWD","KYD","KZT","LAK","LBP","LKR","LRD","LSL","LYD","MAD","MDL","MGA","MKD","MMK","MNT","MOP","MRU","MUR","MVR","MWK","MXN","MYR","MZN","NAD","NGN","NIO","NOK","NPR","NZD","OMR","PAB","PEN","PGK","PHP","PKR","PLN","PYG","QAR","RON","RSD","RUB","RWF","SAR","SBD","SCR","SDG","SEK","SGD","SHP","SLL","SOS","SRD","SSP","STN","SYP","SZL","THB","TJS","TMT","TND","TOP","TRY","TTD","TWD","TZS","UAH","UGX","USD","UYU","UZS","VEF","VND","VUV","WST","XAF","XCD","XOF","XPF","YER","ZAR","ZMW"]`); >+ >+let numberingSystems = Intl.supportedValuesOf("numberingSystem"); >+shouldBe(JSON.stringify(numberingSystems), `["adlm","ahom","arab","arabext","armn","armnlow","bali","beng","bhks","brah","cakm","cham","cyrl","deva","diak","ethi","fullwide","geor","gong","gonm","grek","greklow","gujr","guru","hanidays","hanidec","hans","hansfin","hant","hantfin","hebr","hmng","hmnp","java","jpan","jpanfin","jpanyear","kali","khmr","knda","lana","lanatham","laoo","latn","lepc","limb","mathbold","mathdbl","mathmono","mathsanb","mathsans","mlym","modi","mong","mroo","mtei","mymr","mymrshan","mymrtlng","newa","nkoo","olck","orya","osma","rohg","roman","romanlow","saur","segment","shrd","sind","sinh","sora","sund","takr","talu","taml","tamldec","telu","thai","tibt","tirh","vaii","wara","wcho"]`); >+ >+let timeZones = Intl.supportedValuesOf("timeZone"); >+shouldBe(JSON.stringify(timeZones), `["Africa/Abidjan","Africa/Accra","Africa/Addis_Ababa","Africa/Algiers","Africa/Asmera","Africa/Bamako","Africa/Bangui","Africa/Banjul","Africa/Bissau","Africa/Blantyre","Africa/Brazzaville","Africa/Bujumbura","Africa/Cairo","Africa/Casablanca","Africa/Ceuta","Africa/Conakry","Africa/Dakar","Africa/Dar_es_Salaam","Africa/Djibouti","Africa/Douala","Africa/El_Aaiun","Africa/Freetown","Africa/Gaborone","Africa/Harare","Africa/Johannesburg","Africa/Juba","Africa/Kampala","Africa/Khartoum","Africa/Kigali","Africa/Kinshasa","Africa/Lagos","Africa/Libreville","Africa/Lome","Africa/Luanda","Africa/Lubumbashi","Africa/Lusaka","Africa/Malabo","Africa/Maputo","Africa/Maseru","Africa/Mbabane","Africa/Mogadishu","Africa/Monrovia","Africa/Nairobi","Africa/Ndjamena","Africa/Niamey","Africa/Nouakchott","Africa/Ouagadougou","Africa/Porto-Novo","Africa/Sao_Tome","Africa/Tripoli","Africa/Tunis","Africa/Windhoek","America/Adak","America/Anchorage","America/Anguilla","America/Antigua","America/Araguaina","America/Argentina/La_Rioja","America/Argentina/Rio_Gallegos","America/Argentina/Salta","America/Argentina/San_Juan","America/Argentina/San_Luis","America/Argentina/Tucuman","America/Argentina/Ushuaia","America/Aruba","America/Asuncion","America/Bahia","America/Bahia_Banderas","America/Barbados","America/Belem","America/Belize","America/Blanc-Sablon","America/Boa_Vista","America/Bogota","America/Boise","America/Buenos_Aires","America/Cambridge_Bay","America/Campo_Grande","America/Cancun","America/Caracas","America/Catamarca","America/Cayenne","America/Cayman","America/Chicago","America/Chihuahua","America/Coral_Harbour","America/Cordoba","America/Costa_Rica","America/Creston","America/Cuiaba","America/Curacao","America/Danmarkshavn","America/Dawson","America/Dawson_Creek","America/Denver","America/Detroit","America/Dominica","America/Edmonton","America/Eirunepe","America/El_Salvador","America/Fort_Nelson","America/Fortaleza","America/Glace_Bay","America/Godthab","America/Goose_Bay","America/Grand_Turk","America/Grenada","America/Guadeloupe","America/Guatemala","America/Guayaquil","America/Guyana","America/Halifax","America/Havana","America/Hermosillo","America/Indiana/Knox","America/Indiana/Marengo","America/Indiana/Petersburg","America/Indiana/Tell_City","America/Indiana/Vevay","America/Indiana/Vincennes","America/Indiana/Winamac","America/Indianapolis","America/Inuvik","America/Iqaluit","America/Jamaica","America/Jujuy","America/Juneau","America/Kentucky/Monticello","America/Kralendijk","America/La_Paz","America/Lima","America/Los_Angeles","America/Louisville","America/Lower_Princes","America/Maceio","America/Managua","America/Manaus","America/Marigot","America/Martinique","America/Matamoros","America/Mazatlan","America/Mendoza","America/Menominee","America/Merida","America/Metlakatla","America/Mexico_City","America/Miquelon","America/Moncton","America/Monterrey","America/Montevideo","America/Montreal","America/Montserrat","America/Nassau","America/New_York","America/Nipigon","America/Nome","America/Noronha","America/North_Dakota/Beulah","America/North_Dakota/Center","America/North_Dakota/New_Salem","America/Ojinaga","America/Panama","America/Pangnirtung","America/Paramaribo","America/Phoenix","America/Port-au-Prince","America/Port_of_Spain","America/Porto_Velho","America/Puerto_Rico","America/Punta_Arenas","America/Rainy_River","America/Rankin_Inlet","America/Recife","America/Regina","America/Resolute","America/Rio_Branco","America/Santa_Isabel","America/Santarem","America/Santiago","America/Santo_Domingo","America/Sao_Paulo","America/Scoresbysund","America/Sitka","America/St_Barthelemy","America/St_Johns","America/St_Kitts","America/St_Lucia","America/St_Thomas","America/St_Vincent","America/Swift_Current","America/Tegucigalpa","America/Thule","America/Thunder_Bay","America/Tijuana","America/Toronto","America/Tortola","America/Vancouver","America/Whitehorse","America/Winnipeg","America/Yakutat","America/Yellowknife","Antarctica/Casey","Antarctica/Davis","Antarctica/DumontDUrville","Antarctica/Macquarie","Antarctica/Mawson","Antarctica/McMurdo","Antarctica/Palmer","Antarctica/Rothera","Antarctica/Syowa","Antarctica/Troll","Antarctica/Vostok","Arctic/Longyearbyen","Asia/Aden","Asia/Almaty","Asia/Amman","Asia/Anadyr","Asia/Aqtau","Asia/Aqtobe","Asia/Ashgabat","Asia/Atyrau","Asia/Baghdad","Asia/Bahrain","Asia/Baku","Asia/Bangkok","Asia/Barnaul","Asia/Beirut","Asia/Bishkek","Asia/Brunei","Asia/Calcutta","Asia/Chita","Asia/Choibalsan","Asia/Colombo","Asia/Damascus","Asia/Dhaka","Asia/Dili","Asia/Dubai","Asia/Dushanbe","Asia/Famagusta","Asia/Gaza","Asia/Hebron","Asia/Hong_Kong","Asia/Hovd","Asia/Irkutsk","Asia/Jakarta","Asia/Jayapura","Asia/Jerusalem","Asia/Kabul","Asia/Kamchatka","Asia/Karachi","Asia/Katmandu","Asia/Khandyga","Asia/Krasnoyarsk","Asia/Kuala_Lumpur","Asia/Kuching","Asia/Kuwait","Asia/Macau","Asia/Magadan","Asia/Makassar","Asia/Manila","Asia/Muscat","Asia/Nicosia","Asia/Novokuznetsk","Asia/Novosibirsk","Asia/Omsk","Asia/Oral","Asia/Phnom_Penh","Asia/Pontianak","Asia/Pyongyang","Asia/Qatar","Asia/Qostanay","Asia/Qyzylorda","Asia/Rangoon","Asia/Riyadh","Asia/Saigon","Asia/Sakhalin","Asia/Samarkand","Asia/Seoul","Asia/Shanghai","Asia/Singapore","Asia/Srednekolymsk","Asia/Taipei","Asia/Tashkent","Asia/Tbilisi","Asia/Tehran","Asia/Thimphu","Asia/Tokyo","Asia/Tomsk","Asia/Ulaanbaatar","Asia/Urumqi","Asia/Ust-Nera","Asia/Vientiane","Asia/Vladivostok","Asia/Yakutsk","Asia/Yekaterinburg","Asia/Yerevan","Atlantic/Azores","Atlantic/Bermuda","Atlantic/Canary","Atlantic/Cape_Verde","Atlantic/Faeroe","Atlantic/Madeira","Atlantic/Reykjavik","Atlantic/South_Georgia","Atlantic/St_Helena","Atlantic/Stanley","Australia/Adelaide","Australia/Brisbane","Australia/Broken_Hill","Australia/Currie","Australia/Darwin","Australia/Eucla","Australia/Hobart","Australia/Lindeman","Australia/Lord_Howe","Australia/Melbourne","Australia/Perth","Australia/Sydney","Europe/Amsterdam","Europe/Andorra","Europe/Astrakhan","Europe/Athens","Europe/Belgrade","Europe/Berlin","Europe/Bratislava","Europe/Brussels","Europe/Bucharest","Europe/Budapest","Europe/Busingen","Europe/Chisinau","Europe/Copenhagen","Europe/Dublin","Europe/Gibraltar","Europe/Guernsey","Europe/Helsinki","Europe/Isle_of_Man","Europe/Istanbul","Europe/Jersey","Europe/Kaliningrad","Europe/Kiev","Europe/Kirov","Europe/Lisbon","Europe/Ljubljana","Europe/London","Europe/Luxembourg","Europe/Madrid","Europe/Malta","Europe/Mariehamn","Europe/Minsk","Europe/Monaco","Europe/Moscow","Europe/Oslo","Europe/Paris","Europe/Podgorica","Europe/Prague","Europe/Riga","Europe/Rome","Europe/Samara","Europe/San_Marino","Europe/Sarajevo","Europe/Saratov","Europe/Simferopol","Europe/Skopje","Europe/Sofia","Europe/Stockholm","Europe/Tallinn","Europe/Tirane","Europe/Ulyanovsk","Europe/Uzhgorod","Europe/Vaduz","Europe/Vatican","Europe/Vienna","Europe/Vilnius","Europe/Volgograd","Europe/Warsaw","Europe/Zagreb","Europe/Zaporozhye","Europe/Zurich","Indian/Antananarivo","Indian/Chagos","Indian/Christmas","Indian/Cocos","Indian/Comoro","Indian/Kerguelen","Indian/Mahe","Indian/Maldives","Indian/Mauritius","Indian/Mayotte","Indian/Reunion","Pacific/Apia","Pacific/Auckland","Pacific/Bougainville","Pacific/Chatham","Pacific/Easter","Pacific/Efate","Pacific/Enderbury","Pacific/Fakaofo","Pacific/Fiji","Pacific/Funafuti","Pacific/Galapagos","Pacific/Gambier","Pacific/Guadalcanal","Pacific/Guam","Pacific/Honolulu","Pacific/Johnston","Pacific/Kiritimati","Pacific/Kosrae","Pacific/Kwajalein","Pacific/Majuro","Pacific/Marquesas","Pacific/Midway","Pacific/Nauru","Pacific/Niue","Pacific/Norfolk","Pacific/Noumea","Pacific/Pago_Pago","Pacific/Palau","Pacific/Pitcairn","Pacific/Ponape","Pacific/Port_Moresby","Pacific/Rarotonga","Pacific/Saipan","Pacific/Tahiti","Pacific/Tarawa","Pacific/Tongatapu","Pacific/Truk","Pacific/Wake","Pacific/Wallis"]`); >+ >+let units = Intl.supportedValuesOf("unit"); >+shouldBe(JSON.stringify(units), `["acre","bit","byte","celsius","centimeter","day","degree","fahrenheit","fluid-ounce","foot","gallon","gigabit","gigabyte","gram","hectare","hour","inch","kilobit","kilobyte","kilogram","kilometer","liter","megabit","megabyte","meter","mile","mile-scandinavian","milliliter","millimeter","millisecond","minute","month","ounce","percent","petabyte","pound","second","stone","terabit","terabyte","week","yard","year"]`); >+ >+shouldThrow(() => { >+ Intl.supportedValuesOf("invalid"); >+}, RangeError);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 214795
:
405247
|
405248
|
435960
|
435962
|
436093
|
436094
|
436140
|
436144
|
436145
|
436147