зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1670033 - Part 4: Implement "currency" support for the "Intl Enumeration API" proposal. r=tcampbell
Differential Revision: https://phabricator.services.mozilla.com/D120604
This commit is contained in:
Родитель
0044ff6b13
Коммит
ba8131269e
|
@ -38,6 +38,7 @@
|
|||
#include "js/StableStringChars.h"
|
||||
#include "unicode/ucal.h"
|
||||
#include "unicode/ucol.h"
|
||||
#include "unicode/ucurr.h"
|
||||
#include "unicode/udat.h"
|
||||
#include "unicode/udatpg.h"
|
||||
#include "unicode/uenum.h"
|
||||
|
@ -868,6 +869,54 @@ static ArrayObject* CreateArrayFromList(JSContext* cx,
|
|||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array from an UEnumeration.
|
||||
*/
|
||||
template <const auto& unsupported, const auto& missing>
|
||||
static bool EnumerationIntoList(JSContext* cx, UEnumeration* values,
|
||||
MutableHandle<StringList> list) {
|
||||
while (true) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
int32_t len;
|
||||
const char* value = uenum_next(values, &len, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
intl::ReportInternalError(cx);
|
||||
return false;
|
||||
}
|
||||
if (value == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Skip over known, unsupported values.
|
||||
if (std::any_of(
|
||||
std::begin(unsupported), std::end(unsupported),
|
||||
[value](const auto& e) { return std::strcmp(value, e) == 0; })) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* string = NewStringCopyN<CanGC>(cx, value, size_t(len));
|
||||
if (!string) {
|
||||
return false;
|
||||
}
|
||||
if (!list.append(string)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Add known missing values.
|
||||
for (const char* value : missing) {
|
||||
auto* string = NewStringCopyZ<CanGC>(cx, value);
|
||||
if (!string) {
|
||||
return false;
|
||||
}
|
||||
if (!list.append(string)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array from an UEnumeration.
|
||||
*/
|
||||
|
@ -1012,6 +1061,59 @@ static ArrayObject* AvailableCollations(JSContext* cx) {
|
|||
return CreateArrayFromList(cx, &list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of known, unsupported currencies which are returned by
|
||||
* |ucurr_openISOCurrencies|.
|
||||
*/
|
||||
static constexpr auto UnsupportedCurrencies() {
|
||||
// "MVP" is also marked with "questionable, remove?" in ucurr.cpp, but only
|
||||
// these two currency codes aren't supported by |Intl.DisplayNames| and
|
||||
// therefore must be excluded by |Intl.supportedValuesOf|.
|
||||
return std::array{
|
||||
"EQE", // https://unicode-org.atlassian.net/browse/ICU-21686
|
||||
"LSM", // https://unicode-org.atlassian.net/browse/ICU-21687
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of known, missing currencies which aren't returned by
|
||||
* |ucurr_openISOCurrencies|.
|
||||
*/
|
||||
static constexpr auto MissingCurrencies() {
|
||||
return std::array{
|
||||
"UYW", // https://unicode-org.atlassian.net/browse/ICU-21622
|
||||
"VES", // https://unicode-org.atlassian.net/browse/ICU-21685
|
||||
};
|
||||
}
|
||||
|
||||
// Defined outside of the function to workaround bugs in GCC<9.
|
||||
// Also see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85589>.
|
||||
static constexpr auto UnsupportedCurrenciesArray = UnsupportedCurrencies();
|
||||
static constexpr auto MissingCurrenciesArray = MissingCurrencies();
|
||||
|
||||
/**
|
||||
* AvailableCurrencies ( )
|
||||
*/
|
||||
static ArrayObject* AvailableCurrencies(JSContext* cx) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UEnumeration* values = ucurr_openISOCurrencies(UCURR_ALL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
intl::ReportInternalError(cx);
|
||||
return nullptr;
|
||||
}
|
||||
ScopedICUObject<UEnumeration, CloseEnumeration> toClose(values);
|
||||
|
||||
static constexpr auto& unsupported = UnsupportedCurrenciesArray;
|
||||
static constexpr auto& missing = MissingCurrenciesArray;
|
||||
|
||||
Rooted<StringList> list(cx, StringList(cx));
|
||||
if (!EnumerationIntoList<unsupported, missing>(cx, values, &list)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return CreateArrayFromList(cx, &list);
|
||||
}
|
||||
|
||||
bool js::intl_SupportedValuesOf(JSContext* cx, unsigned argc, JS::Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 1);
|
||||
|
@ -1027,6 +1129,8 @@ bool js::intl_SupportedValuesOf(JSContext* cx, unsigned argc, JS::Value* vp) {
|
|||
list = AvailableCalendars(cx);
|
||||
} else if (StringEqualsLiteral(key, "collation")) {
|
||||
list = AvailableCollations(cx);
|
||||
} else if (StringEqualsLiteral(key, "currency")) {
|
||||
list = AvailableCurrencies(cx);
|
||||
} else {
|
||||
ReportBadKey(cx, key);
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
|
||||
|
||||
const currencies = Intl.supportedValuesOf("currency");
|
||||
|
||||
assertEq(new Set(currencies).size, currencies.length, "No duplicates are present");
|
||||
assertEqArray(currencies, [...currencies].sort(), "The list is sorted");
|
||||
|
||||
const codeRE = /^[A-Z]{3}$/;
|
||||
for (let currency of currencies) {
|
||||
assertEq(codeRE.test(currency), true, `${currency} is a 3-letter ISO 4217 currency code`);
|
||||
}
|
||||
|
||||
for (let currency of currencies) {
|
||||
let obj = new Intl.NumberFormat("en", {style: "currency", currency});
|
||||
assertEq(obj.resolvedOptions().currency, currency, `${currency} is supported by NumberFormat`);
|
||||
}
|
||||
|
||||
for (let currency of currencies) {
|
||||
let obj = new Intl.DisplayNames("en", {type: "currency", fallback: "none"});
|
||||
assertEq(typeof obj.of(currency), "string", `${currency} is supported by DisplayNames`);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
Загрузка…
Ссылка в новой задаче