зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1715007 - Part 1: Add testing function to retrieve all available locales. r=tcampbell
Add a testing function to retrieve all available locales in preparation to test the changes in part two. Differential Revision: https://phabricator.services.mozilla.com/D117016
This commit is contained in:
Родитель
c121de17f1
Коммит
5fb308d38c
|
@ -40,6 +40,7 @@
|
|||
|
||||
#ifdef JS_HAS_INTL_API
|
||||
# include "builtin/intl/CommonFunctions.h"
|
||||
# include "builtin/intl/SharedIntlData.h"
|
||||
#endif
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "builtin/Promise.h"
|
||||
|
@ -7177,6 +7178,64 @@ static bool GetICUOptions(JSContext* cx, unsigned argc, Value* vp) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool GetAvailableLocalesOf(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedObject callee(cx, &args.callee());
|
||||
|
||||
if (!args.requireAtLeast(cx, "getAvailableLocalesOf", 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HandleValue arg = args[0];
|
||||
if (!arg.isString()) {
|
||||
ReportUsageErrorASCII(cx, callee, "First argument must be a string");
|
||||
return false;
|
||||
}
|
||||
|
||||
ArrayObject* result;
|
||||
#ifdef JS_HAS_INTL_API
|
||||
using SupportedLocaleKind = js::intl::SharedIntlData::SupportedLocaleKind;
|
||||
|
||||
SupportedLocaleKind kind;
|
||||
{
|
||||
JSLinearString* typeStr = arg.toString()->ensureLinear(cx);
|
||||
if (!typeStr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (StringEqualsLiteral(typeStr, "Collator")) {
|
||||
kind = SupportedLocaleKind::Collator;
|
||||
} else if (StringEqualsLiteral(typeStr, "DateTimeFormat")) {
|
||||
kind = SupportedLocaleKind::DateTimeFormat;
|
||||
} else if (StringEqualsLiteral(typeStr, "DisplayNames")) {
|
||||
kind = SupportedLocaleKind::DisplayNames;
|
||||
} else if (StringEqualsLiteral(typeStr, "ListFormat")) {
|
||||
kind = SupportedLocaleKind::ListFormat;
|
||||
} else if (StringEqualsLiteral(typeStr, "NumberFormat")) {
|
||||
kind = SupportedLocaleKind::NumberFormat;
|
||||
} else if (StringEqualsLiteral(typeStr, "PluralRules")) {
|
||||
kind = SupportedLocaleKind::PluralRules;
|
||||
} else if (StringEqualsLiteral(typeStr, "RelativeTimeFormat")) {
|
||||
kind = SupportedLocaleKind::RelativeTimeFormat;
|
||||
} else {
|
||||
ReportUsageErrorASCII(cx, callee, "Unsupported Intl constructor name");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
intl::SharedIntlData& sharedIntlData = cx->runtime()->sharedIntlData.ref();
|
||||
result = sharedIntlData.availableLocalesOf(cx, kind);
|
||||
#else
|
||||
result = NewDenseEmptyArray(cx);
|
||||
#endif
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsSmallFunction(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
RootedObject callee(cx, &args.callee());
|
||||
|
@ -8221,7 +8280,6 @@ JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE)
|
|||
"sequence of ECMAScript execution completes. This is used for testing\n"
|
||||
"WeakRefs.\n"),
|
||||
|
||||
|
||||
JS_FN_HELP("numberToDouble", NumberToDouble, 1, 0,
|
||||
"numberToDouble(number)",
|
||||
" Return the input number as double-typed number."),
|
||||
|
@ -8236,6 +8294,10 @@ JS_FN_HELP("getICUOptions", GetICUOptions, 0, 0,
|
|||
" timezone: the ICU default time zone, e.g. 'America/Los_Angeles'\n"
|
||||
" host-timezone: the host time zone, e.g. 'America/Los_Angeles'"),
|
||||
|
||||
JS_FN_HELP("getAvailableLocalesOf", GetAvailableLocalesOf, 0, 0,
|
||||
"getAvailableLocalesOf(name)",
|
||||
" Return an array of all available locales for the given Intl constuctor."),
|
||||
|
||||
JS_FN_HELP("isSmallFunction", IsSmallFunction, 1, 0,
|
||||
"isSmallFunction(fun)",
|
||||
" Returns true if a scripted function is small enough to be inlinable."),
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <stdint.h>
|
||||
#include <utility>
|
||||
|
||||
#include "builtin/Array.h"
|
||||
#include "builtin/intl/CommonFunctions.h"
|
||||
#include "builtin/intl/ScopedICUObject.h"
|
||||
#include "builtin/intl/TimeZoneDataGenerated.h"
|
||||
|
@ -31,7 +32,9 @@
|
|||
#include "unicode/uloc.h"
|
||||
#include "unicode/unum.h"
|
||||
#include "unicode/utypes.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/StringType.h"
|
||||
|
||||
using js::HashNumber;
|
||||
|
@ -484,6 +487,48 @@ bool js::intl::SharedIntlData::isSupportedLocale(JSContext* cx,
|
|||
MOZ_CRASH("Invalid Intl constructor");
|
||||
}
|
||||
|
||||
js::ArrayObject* js::intl::SharedIntlData::availableLocalesOf(
|
||||
JSContext* cx, SupportedLocaleKind kind) {
|
||||
if (!ensureSupportedLocales(cx)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LocaleSet* localeSet = nullptr;
|
||||
switch (kind) {
|
||||
case SupportedLocaleKind::Collator:
|
||||
localeSet = &collatorSupportedLocales;
|
||||
break;
|
||||
case SupportedLocaleKind::DateTimeFormat:
|
||||
case SupportedLocaleKind::DisplayNames:
|
||||
case SupportedLocaleKind::ListFormat:
|
||||
case SupportedLocaleKind::NumberFormat:
|
||||
case SupportedLocaleKind::PluralRules:
|
||||
case SupportedLocaleKind::RelativeTimeFormat:
|
||||
localeSet = &supportedLocales;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Invalid Intl constructor");
|
||||
}
|
||||
|
||||
const uint32_t count = localeSet->count();
|
||||
ArrayObject* result = NewDenseFullyAllocatedArray(cx, count);
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
result->setDenseInitializedLength(count);
|
||||
|
||||
uint32_t index = 0;
|
||||
for (auto range = localeSet->iter(); !range.done(); range.next()) {
|
||||
JSAtom* locale = range.get();
|
||||
cx->markAtom(locale);
|
||||
|
||||
result->initDenseElement(index++, StringValue(locale));
|
||||
}
|
||||
MOZ_ASSERT(index == count);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if DEBUG || MOZ_SYSTEM_ICU
|
||||
bool js::intl::SharedIntlData::ensureUpperCaseFirstLocales(JSContext* cx) {
|
||||
if (upperCaseFirstInitialized) {
|
||||
|
|
|
@ -26,6 +26,8 @@ class DateTimePatternGenerator;
|
|||
|
||||
namespace js {
|
||||
|
||||
class ArrayObject;
|
||||
|
||||
namespace intl {
|
||||
|
||||
/**
|
||||
|
@ -245,6 +247,11 @@ class SharedIntlData {
|
|||
JS::Handle<JSString*> locale,
|
||||
bool* supported);
|
||||
|
||||
/**
|
||||
* Returns all available locales for |kind|.
|
||||
*/
|
||||
ArrayObject* availableLocalesOf(JSContext* cx, SupportedLocaleKind kind);
|
||||
|
||||
private:
|
||||
/**
|
||||
* The case first parameter (BCP47 key "kf") allows to switch the order of
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty('Intl'))
|
||||
|
||||
if (typeof getAvailableLocalesOf === "undefined") {
|
||||
var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
|
||||
}
|
||||
|
||||
function IsIntlService(c) {
|
||||
return typeof c === "function" &&
|
||||
c.hasOwnProperty("prototype") &&
|
||||
c.prototype.hasOwnProperty("resolvedOptions");
|
||||
}
|
||||
|
||||
const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
|
||||
|
||||
// Test all Intl service constructors.
|
||||
for (let intlConstructor of intlConstructors) {
|
||||
// Retrieve all available locales of the given Intl service constructor.
|
||||
let available = getAvailableLocalesOf(intlConstructor.name);
|
||||
|
||||
// "best fit" matchers could potentially return a different locale, so we only
|
||||
// test with "lookup" locale matchers. (NB: We don't yet support "best fit"
|
||||
// matchers.)
|
||||
let options = {localeMatcher: "lookup"};
|
||||
|
||||
if (intlConstructor === Intl.DisplayNames) {
|
||||
// Intl.DisplayNames can't be constructed without the "type" option.
|
||||
options.type = "language";
|
||||
}
|
||||
|
||||
for (let locale of available) {
|
||||
let obj = new intlConstructor(locale, options);
|
||||
let resolved = obj.resolvedOptions();
|
||||
|
||||
// If |locale| is an available locale, the "lookup" locale matcher should
|
||||
// pick exactly that locale.
|
||||
assertEq(resolved.locale, locale);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,26 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty('Intl'))
|
||||
|
||||
if (typeof getAvailableLocalesOf === "undefined") {
|
||||
var getAvailableLocalesOf = SpecialPowers.Cu.getJSTestingFunctions().getAvailableLocalesOf;
|
||||
}
|
||||
|
||||
function IsIntlService(c) {
|
||||
return typeof c === "function" &&
|
||||
c.hasOwnProperty("prototype") &&
|
||||
c.prototype.hasOwnProperty("resolvedOptions");
|
||||
}
|
||||
|
||||
const intlConstructors = Object.getOwnPropertyNames(Intl).map(name => Intl[name]).filter(IsIntlService);
|
||||
|
||||
// Test all Intl service constructors.
|
||||
for (let intlConstructor of intlConstructors) {
|
||||
// Retrieve all available locales of the given Intl service constructor.
|
||||
let available = getAvailableLocalesOf(intlConstructor.name);
|
||||
|
||||
// All available locales must be reported as supported.
|
||||
let supported = intlConstructor.supportedLocalesOf(available);
|
||||
assertEqArray(supported, available);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
Загрузка…
Ссылка в новой задаче