зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1639515 - Part 6: Remove no longer used Intl.getDisplayNames. r=platform-i18n-reviewers,gregtatum
This function is no longer needed after part 5. Differential Revision: https://phabricator.services.mozilla.com/D76118
This commit is contained in:
Родитель
1d8f2c8af6
Коммит
691b7f9b13
|
@ -10,8 +10,6 @@
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/intl/Calendar.h"
|
#include "mozilla/intl/Calendar.h"
|
||||||
#include "mozilla/Likely.h"
|
|
||||||
#include "mozilla/Range.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -43,8 +41,6 @@
|
||||||
#include "unicode/ucal.h"
|
#include "unicode/ucal.h"
|
||||||
#include "unicode/ucol.h"
|
#include "unicode/ucol.h"
|
||||||
#include "unicode/ucurr.h"
|
#include "unicode/ucurr.h"
|
||||||
#include "unicode/udat.h"
|
|
||||||
#include "unicode/udatpg.h"
|
|
||||||
#include "unicode/uenum.h"
|
#include "unicode/uenum.h"
|
||||||
#include "unicode/uloc.h"
|
#include "unicode/uloc.h"
|
||||||
#include "unicode/utypes.h"
|
#include "unicode/utypes.h"
|
||||||
|
@ -61,13 +57,6 @@
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
using mozilla::Range;
|
|
||||||
using mozilla::RangedPtr;
|
|
||||||
|
|
||||||
using JS::AutoStableStringChars;
|
|
||||||
|
|
||||||
using js::intl::CallICU;
|
|
||||||
using js::intl::DateTimeFormatOptions;
|
|
||||||
using js::intl::IcuLocale;
|
using js::intl::IcuLocale;
|
||||||
|
|
||||||
/******************** Intl ********************/
|
/******************** Intl ********************/
|
||||||
|
@ -176,324 +165,6 @@ static void ReportBadKey(JSContext* cx, JSString* key) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ConstChar>
|
|
||||||
static bool MatchPart(RangedPtr<ConstChar> iter, const RangedPtr<ConstChar> end,
|
|
||||||
const char* part, size_t partlen) {
|
|
||||||
for (size_t i = 0; i < partlen; iter++, i++) {
|
|
||||||
if (iter == end || *iter != part[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ConstChar, size_t N>
|
|
||||||
inline bool MatchPart(RangedPtr<ConstChar>* iter,
|
|
||||||
const RangedPtr<ConstChar> end, const char (&part)[N]) {
|
|
||||||
if (!MatchPart(*iter, end, part, N - 1)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*iter += N - 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class DisplayNameStyle {
|
|
||||||
Narrow,
|
|
||||||
Short,
|
|
||||||
Long,
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ConstChar>
|
|
||||||
static JSString* ComputeSingleDisplayName(JSContext* cx, UDateFormat* fmt,
|
|
||||||
UDateTimePatternGenerator* dtpg,
|
|
||||||
DisplayNameStyle style,
|
|
||||||
const Range<ConstChar>& pattern,
|
|
||||||
HandleString patternString) {
|
|
||||||
RangedPtr<ConstChar> iter = pattern.begin();
|
|
||||||
const RangedPtr<ConstChar> end = pattern.end();
|
|
||||||
|
|
||||||
auto MatchSlash = [cx, patternString, &iter, end]() {
|
|
||||||
if (MOZ_LIKELY(iter != end && *iter == '/')) {
|
|
||||||
iter++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReportBadKey(cx, patternString);
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!MatchPart(&iter, end, "dates")) {
|
|
||||||
ReportBadKey(cx, patternString);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MatchSlash()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MatchPart(&iter, end, "fields")) {
|
|
||||||
if (!MatchSlash()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
UDateTimePatternField fieldType;
|
|
||||||
|
|
||||||
if (MatchPart(&iter, end, "year")) {
|
|
||||||
fieldType = UDATPG_YEAR_FIELD;
|
|
||||||
} else if (MatchPart(&iter, end, "month")) {
|
|
||||||
fieldType = UDATPG_MONTH_FIELD;
|
|
||||||
} else if (MatchPart(&iter, end, "week")) {
|
|
||||||
fieldType = UDATPG_WEEK_OF_YEAR_FIELD;
|
|
||||||
} else if (MatchPart(&iter, end, "day")) {
|
|
||||||
fieldType = UDATPG_DAY_FIELD;
|
|
||||||
} else {
|
|
||||||
ReportBadKey(cx, patternString);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This part must be the final part with no trailing data.
|
|
||||||
if (iter != end) {
|
|
||||||
ReportBadKey(cx, patternString);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t resultSize;
|
|
||||||
const UChar* value = udatpg_getAppendItemName(dtpg, fieldType, &resultSize);
|
|
||||||
MOZ_ASSERT(resultSize >= 0);
|
|
||||||
|
|
||||||
return NewStringCopyN<CanGC>(cx, value, size_t(resultSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MatchPart(&iter, end, "gregorian")) {
|
|
||||||
if (!MatchSlash()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
UDateFormatSymbolType symbolType;
|
|
||||||
int32_t index;
|
|
||||||
|
|
||||||
if (MatchPart(&iter, end, "months")) {
|
|
||||||
if (!MatchSlash()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (style) {
|
|
||||||
case DisplayNameStyle::Narrow:
|
|
||||||
symbolType = UDAT_STANDALONE_NARROW_MONTHS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DisplayNameStyle::Short:
|
|
||||||
symbolType = UDAT_STANDALONE_SHORT_MONTHS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DisplayNameStyle::Long:
|
|
||||||
symbolType = UDAT_STANDALONE_MONTHS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MatchPart(&iter, end, "january")) {
|
|
||||||
index = UCAL_JANUARY;
|
|
||||||
} else if (MatchPart(&iter, end, "february")) {
|
|
||||||
index = UCAL_FEBRUARY;
|
|
||||||
} else if (MatchPart(&iter, end, "march")) {
|
|
||||||
index = UCAL_MARCH;
|
|
||||||
} else if (MatchPart(&iter, end, "april")) {
|
|
||||||
index = UCAL_APRIL;
|
|
||||||
} else if (MatchPart(&iter, end, "may")) {
|
|
||||||
index = UCAL_MAY;
|
|
||||||
} else if (MatchPart(&iter, end, "june")) {
|
|
||||||
index = UCAL_JUNE;
|
|
||||||
} else if (MatchPart(&iter, end, "july")) {
|
|
||||||
index = UCAL_JULY;
|
|
||||||
} else if (MatchPart(&iter, end, "august")) {
|
|
||||||
index = UCAL_AUGUST;
|
|
||||||
} else if (MatchPart(&iter, end, "september")) {
|
|
||||||
index = UCAL_SEPTEMBER;
|
|
||||||
} else if (MatchPart(&iter, end, "october")) {
|
|
||||||
index = UCAL_OCTOBER;
|
|
||||||
} else if (MatchPart(&iter, end, "november")) {
|
|
||||||
index = UCAL_NOVEMBER;
|
|
||||||
} else if (MatchPart(&iter, end, "december")) {
|
|
||||||
index = UCAL_DECEMBER;
|
|
||||||
} else {
|
|
||||||
ReportBadKey(cx, patternString);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
} else if (MatchPart(&iter, end, "weekdays")) {
|
|
||||||
if (!MatchSlash()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (style) {
|
|
||||||
case DisplayNameStyle::Narrow:
|
|
||||||
symbolType = UDAT_STANDALONE_NARROW_WEEKDAYS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DisplayNameStyle::Short:
|
|
||||||
symbolType = UDAT_STANDALONE_SHORT_WEEKDAYS;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DisplayNameStyle::Long:
|
|
||||||
symbolType = UDAT_STANDALONE_WEEKDAYS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MatchPart(&iter, end, "monday")) {
|
|
||||||
index = UCAL_MONDAY;
|
|
||||||
} else if (MatchPart(&iter, end, "tuesday")) {
|
|
||||||
index = UCAL_TUESDAY;
|
|
||||||
} else if (MatchPart(&iter, end, "wednesday")) {
|
|
||||||
index = UCAL_WEDNESDAY;
|
|
||||||
} else if (MatchPart(&iter, end, "thursday")) {
|
|
||||||
index = UCAL_THURSDAY;
|
|
||||||
} else if (MatchPart(&iter, end, "friday")) {
|
|
||||||
index = UCAL_FRIDAY;
|
|
||||||
} else if (MatchPart(&iter, end, "saturday")) {
|
|
||||||
index = UCAL_SATURDAY;
|
|
||||||
} else if (MatchPart(&iter, end, "sunday")) {
|
|
||||||
index = UCAL_SUNDAY;
|
|
||||||
} else {
|
|
||||||
ReportBadKey(cx, patternString);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
} else if (MatchPart(&iter, end, "dayperiods")) {
|
|
||||||
if (!MatchSlash()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
symbolType = UDAT_AM_PMS;
|
|
||||||
|
|
||||||
if (MatchPart(&iter, end, "am")) {
|
|
||||||
index = UCAL_AM;
|
|
||||||
} else if (MatchPart(&iter, end, "pm")) {
|
|
||||||
index = UCAL_PM;
|
|
||||||
} else {
|
|
||||||
ReportBadKey(cx, patternString);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ReportBadKey(cx, patternString);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This part must be the final part with no trailing data.
|
|
||||||
if (iter != end) {
|
|
||||||
ReportBadKey(cx, patternString);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CallICU(cx, [fmt, symbolType, index](UChar* chars, int32_t size,
|
|
||||||
UErrorCode* status) {
|
|
||||||
return udat_getSymbols(fmt, symbolType, index, chars, size, status);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ReportBadKey(cx, patternString);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool js::intl_ComputeDisplayNames(JSContext* cx, unsigned argc, Value* vp) {
|
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
|
||||||
MOZ_ASSERT(args.length() == 3);
|
|
||||||
|
|
||||||
// 1. Assert: locale is a string.
|
|
||||||
UniqueChars locale = intl::EncodeLocale(cx, args[0].toString());
|
|
||||||
if (!locale) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Assert: style is a string.
|
|
||||||
DisplayNameStyle dnStyle;
|
|
||||||
{
|
|
||||||
JSLinearString* style = args[1].toString()->ensureLinear(cx);
|
|
||||||
if (!style) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringEqualsLiteral(style, "narrow")) {
|
|
||||||
dnStyle = DisplayNameStyle::Narrow;
|
|
||||||
} else if (StringEqualsLiteral(style, "short")) {
|
|
||||||
dnStyle = DisplayNameStyle::Short;
|
|
||||||
} else {
|
|
||||||
MOZ_ASSERT(StringEqualsLiteral(style, "long"));
|
|
||||||
dnStyle = DisplayNameStyle::Long;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Assert: keys is an Array.
|
|
||||||
RootedArrayObject keys(cx, &args[2].toObject().as<ArrayObject>());
|
|
||||||
if (!keys) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Let result be ArrayCreate(0).
|
|
||||||
RootedArrayObject result(cx, NewDenseFullyAllocatedArray(cx, keys->length()));
|
|
||||||
if (!result) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
result->ensureDenseInitializedLength(0, keys->length());
|
|
||||||
|
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
|
||||||
|
|
||||||
UDateFormat* fmt =
|
|
||||||
udat_open(UDAT_DEFAULT, UDAT_DEFAULT, IcuLocale(locale.get()), nullptr, 0,
|
|
||||||
nullptr, 0, &status);
|
|
||||||
if (U_FAILURE(status)) {
|
|
||||||
intl::ReportInternalError(cx);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ScopedICUObject<UDateFormat, udat_close> datToClose(fmt);
|
|
||||||
|
|
||||||
// UDateTimePatternGenerator will be needed for translations of date and
|
|
||||||
// time fields like "month", "week", "day" etc.
|
|
||||||
UDateTimePatternGenerator* dtpg =
|
|
||||||
udatpg_open(IcuLocale(locale.get()), &status);
|
|
||||||
if (U_FAILURE(status)) {
|
|
||||||
intl::ReportInternalError(cx);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ScopedICUObject<UDateTimePatternGenerator, udatpg_close> datPgToClose(dtpg);
|
|
||||||
|
|
||||||
// 5. For each element of keys,
|
|
||||||
RootedString keyValStr(cx);
|
|
||||||
RootedValue v(cx);
|
|
||||||
for (uint32_t i = 0; i < keys->length(); i++) {
|
|
||||||
if (!GetElement(cx, keys, keys, i, &v)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
keyValStr = v.toString();
|
|
||||||
|
|
||||||
AutoStableStringChars stablePatternChars(cx);
|
|
||||||
if (!stablePatternChars.init(cx, keyValStr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5.a. Perform an implementation dependent algorithm to map a key to a
|
|
||||||
// corresponding display name.
|
|
||||||
JSString* displayName =
|
|
||||||
stablePatternChars.isLatin1()
|
|
||||||
? ComputeSingleDisplayName(cx, fmt, dtpg, dnStyle,
|
|
||||||
stablePatternChars.latin1Range(),
|
|
||||||
keyValStr)
|
|
||||||
: ComputeSingleDisplayName(cx, fmt, dtpg, dnStyle,
|
|
||||||
stablePatternChars.twoByteRange(),
|
|
||||||
keyValStr);
|
|
||||||
if (!displayName) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5.b. Append the result string to result.
|
|
||||||
result->setDenseElement(i, StringValue(displayName));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Return result.
|
|
||||||
args.rval().setObject(*result);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool SameOrParentLocale(JSLinearString* locale,
|
static bool SameOrParentLocale(JSLinearString* locale,
|
||||||
JSLinearString* otherLocale) {
|
JSLinearString* otherLocale) {
|
||||||
// Return true if |locale| is the same locale as |otherLocale|.
|
// Return true if |locale| is the same locale as |otherLocale|.
|
||||||
|
|
|
@ -41,47 +41,6 @@ extern const JSClass IntlClass;
|
||||||
[[nodiscard]] extern bool intl_GetCalendarInfo(JSContext* cx, unsigned argc,
|
[[nodiscard]] extern bool intl_GetCalendarInfo(JSContext* cx, unsigned argc,
|
||||||
JS::Value* vp);
|
JS::Value* vp);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an Array with CLDR-based fields display names.
|
|
||||||
* The function takes three arguments:
|
|
||||||
*
|
|
||||||
* locale
|
|
||||||
* BCP47 compliant locale string
|
|
||||||
* style
|
|
||||||
* A string with values: long or short or narrow
|
|
||||||
* keys
|
|
||||||
* An array or path-like strings that identify keys to be returned
|
|
||||||
* At the moment the following types of keys are supported:
|
|
||||||
*
|
|
||||||
* 'dates/fields/{year|month|week|day}'
|
|
||||||
* 'dates/gregorian/months/{january|...|december}'
|
|
||||||
* 'dates/gregorian/weekdays/{sunday|...|saturday}'
|
|
||||||
* 'dates/gregorian/dayperiods/{am|pm}'
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
|
||||||
* let info = intl_ComputeDisplayNames(
|
|
||||||
* 'en-US',
|
|
||||||
* 'long',
|
|
||||||
* [
|
|
||||||
* 'dates/fields/year',
|
|
||||||
* 'dates/gregorian/months/january',
|
|
||||||
* 'dates/gregorian/weekdays/monday',
|
|
||||||
* 'dates/gregorian/dayperiods/am',
|
|
||||||
* ]
|
|
||||||
* );
|
|
||||||
*
|
|
||||||
* Returned value:
|
|
||||||
*
|
|
||||||
* [
|
|
||||||
* 'year',
|
|
||||||
* 'January',
|
|
||||||
* 'Monday',
|
|
||||||
* 'AM'
|
|
||||||
* ]
|
|
||||||
*/
|
|
||||||
[[nodiscard]] extern bool intl_ComputeDisplayNames(JSContext* cx, unsigned argc,
|
|
||||||
JS::Value* vp);
|
|
||||||
/**
|
/**
|
||||||
* Compares a BCP 47 language tag against the locales in availableLocales and
|
* Compares a BCP 47 language tag against the locales in availableLocales and
|
||||||
* returns the best available match -- or |undefined| if no match was found.
|
* returns the best available match -- or |undefined| if no match was found.
|
||||||
|
|
|
@ -80,129 +80,3 @@ function Intl_getCalendarInfo(locales) {
|
||||||
// 7. Return result.
|
// 7. Return result.
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This function is a custom function in the style of the standard Intl.*
|
|
||||||
* functions, that isn't part of any spec or proposal yet.
|
|
||||||
* We want to use it internally to retrieve translated values from CLDR in
|
|
||||||
* order to ensure they're aligned with what Intl API returns.
|
|
||||||
*
|
|
||||||
* This API may one day be a foundation for an ECMA402 API spec proposal.
|
|
||||||
*
|
|
||||||
* The function takes two arguments - locales which is a list of locale strings
|
|
||||||
* and options which is an object with two optional properties:
|
|
||||||
*
|
|
||||||
* keys:
|
|
||||||
* an Array of string values that are paths to individual terms
|
|
||||||
*
|
|
||||||
* style:
|
|
||||||
* a String with a value "long", "short" or "narrow"
|
|
||||||
*
|
|
||||||
* It returns an object with properties:
|
|
||||||
*
|
|
||||||
* locale:
|
|
||||||
* a negotiated locale string
|
|
||||||
*
|
|
||||||
* style:
|
|
||||||
* negotiated style
|
|
||||||
*
|
|
||||||
* values:
|
|
||||||
* A key-value pair list of requested keys and corresponding
|
|
||||||
* translated values
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
function Intl_getDisplayNames(locales, options) {
|
|
||||||
// 1. Let requestLocales be ? CanonicalizeLocaleList(locales).
|
|
||||||
const requestedLocales = CanonicalizeLocaleList(locales);
|
|
||||||
|
|
||||||
// 2. If options is undefined, then
|
|
||||||
if (options === undefined)
|
|
||||||
// a. Let options be ObjectCreate(null).
|
|
||||||
options = std_Object_create(null);
|
|
||||||
// 3. Else,
|
|
||||||
else
|
|
||||||
// a. Let options be ? ToObject(options).
|
|
||||||
options = ToObject(options);
|
|
||||||
|
|
||||||
const DateTimeFormat = dateTimeFormatInternalProperties;
|
|
||||||
|
|
||||||
// 4. Let localeData be %DateTimeFormat%.[[localeData]].
|
|
||||||
const localeData = DateTimeFormat.localeData;
|
|
||||||
|
|
||||||
// 5. Let localeOpt be a new Record.
|
|
||||||
const localeOpt = new_Record();
|
|
||||||
|
|
||||||
// 6. Set localeOpt.[[localeMatcher]] to "best fit".
|
|
||||||
localeOpt.localeMatcher = "best fit";
|
|
||||||
|
|
||||||
// 7. Let r be ResolveLocale(%DateTimeFormat%.[[availableLocales]], requestedLocales, localeOpt,
|
|
||||||
// %DateTimeFormat%.[[relevantExtensionKeys]], localeData).
|
|
||||||
const r = ResolveLocale("DateTimeFormat",
|
|
||||||
requestedLocales,
|
|
||||||
localeOpt,
|
|
||||||
DateTimeFormat.relevantExtensionKeys,
|
|
||||||
localeData);
|
|
||||||
|
|
||||||
// 8. Let style be ? GetOption(options, "style", "string", « "long", "short", "narrow" », "long").
|
|
||||||
const style = GetOption(options, "style", "string", ["long", "short", "narrow"], "long");
|
|
||||||
|
|
||||||
// 9. Let keys be ? Get(options, "keys").
|
|
||||||
let keys = options.keys;
|
|
||||||
|
|
||||||
// 10. If keys is undefined,
|
|
||||||
if (keys === undefined) {
|
|
||||||
// a. Let keys be ArrayCreate(0).
|
|
||||||
keys = [];
|
|
||||||
} else if (!IsObject(keys)) {
|
|
||||||
// 11. Else,
|
|
||||||
// a. If Type(keys) is not Object, throw a TypeError exception.
|
|
||||||
ThrowTypeError(JSMSG_INVALID_KEYS_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 12. Let processedKeys be ArrayCreate(0).
|
|
||||||
// (This really should be a List, but we use an Array here in order that
|
|
||||||
// |intl_ComputeDisplayNames| may infallibly access the list's length via
|
|
||||||
// |ArrayObject::length|.)
|
|
||||||
let processedKeys = [];
|
|
||||||
|
|
||||||
// 13. Let len be ? ToLength(? Get(keys, "length")).
|
|
||||||
let len = ToLength(keys.length);
|
|
||||||
|
|
||||||
// 14. Let i be 0.
|
|
||||||
// 15. Repeat, while i < len
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
// a. Let processedKey be ? ToString(? Get(keys, i)).
|
|
||||||
// b. Perform ? CreateDataPropertyOrThrow(processedKeys, i, processedKey).
|
|
||||||
DefineDataProperty(processedKeys, i, ToString(keys[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 16. Let names be ? ComputeDisplayNames(r.[[locale]], style, processedKeys).
|
|
||||||
const names = intl_ComputeDisplayNames(r.locale, style, processedKeys);
|
|
||||||
|
|
||||||
// 17. Let values be ObjectCreate(%ObjectPrototype%).
|
|
||||||
const values = {};
|
|
||||||
|
|
||||||
// 18. Set i to 0.
|
|
||||||
// 19. Repeat, while i < len
|
|
||||||
for (let i = 0; i < len; i++) {
|
|
||||||
// a. Let key be ? Get(processedKeys, i).
|
|
||||||
const key = processedKeys[i];
|
|
||||||
// b. Let name be ? Get(names, i).
|
|
||||||
const name = names[i];
|
|
||||||
// c. Assert: Type(name) is string.
|
|
||||||
assert(typeof name === "string", "unexpected non-string value");
|
|
||||||
// d. Assert: the length of name is greater than zero.
|
|
||||||
assert(name.length > 0, "empty string value");
|
|
||||||
// e. Perform ? DefinePropertyOrThrow(values, key, name).
|
|
||||||
DefineDataProperty(values, key, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 20. Let options be ObjectCreate(%ObjectPrototype%).
|
|
||||||
// 21. Perform ! DefinePropertyOrThrow(result, "locale", r.[[locale]]).
|
|
||||||
// 22. Perform ! DefinePropertyOrThrow(result, "style", style).
|
|
||||||
// 23. Perform ! DefinePropertyOrThrow(result, "values", values).
|
|
||||||
const result = { locale: r.locale, style, values };
|
|
||||||
|
|
||||||
// 24. Return result.
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
if (this.Intl) {
|
|
||||||
Object.defineProperty(Object.prototype, 0, {
|
|
||||||
set: function() {}
|
|
||||||
});
|
|
||||||
function checkDisplayNames(names, expected) {}
|
|
||||||
addIntlExtras(Intl);
|
|
||||||
let gDN = Intl.getDisplayNames;
|
|
||||||
checkDisplayNames(gDN('ar', {
|
|
||||||
keys: ['dates/fields/month', ]
|
|
||||||
}), {});
|
|
||||||
}
|
|
|
@ -1474,7 +1474,6 @@ static bool AddIntlExtras(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
|
|
||||||
static const JSFunctionSpec funcs[] = {
|
static const JSFunctionSpec funcs[] = {
|
||||||
JS_SELF_HOSTED_FN("getCalendarInfo", "Intl_getCalendarInfo", 1, 0),
|
JS_SELF_HOSTED_FN("getCalendarInfo", "Intl_getCalendarInfo", 1, 0),
|
||||||
JS_SELF_HOSTED_FN("getDisplayNames", "Intl_getDisplayNames", 2, 0),
|
|
||||||
JS_FS_END};
|
JS_FS_END};
|
||||||
|
|
||||||
if (!JS_DefineFunctions(cx, intl, funcs)) {
|
if (!JS_DefineFunctions(cx, intl, funcs)) {
|
||||||
|
|
|
@ -1,246 +0,0 @@
|
||||||
// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras'))
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
// Tests the getCalendarInfo function with a diverse set of arguments.
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Test if getDisplayNames return value matches expected values.
|
|
||||||
*/
|
|
||||||
function checkDisplayNames(names, expected)
|
|
||||||
{
|
|
||||||
assertEq(Object.getPrototypeOf(names), Object.prototype);
|
|
||||||
|
|
||||||
assertEq(names.locale, expected.locale);
|
|
||||||
assertEq(names.style, expected.style);
|
|
||||||
|
|
||||||
const nameValues = names.values;
|
|
||||||
const expectedValues = expected.values;
|
|
||||||
|
|
||||||
const nameValuesKeys = Object.getOwnPropertyNames(nameValues).sort();
|
|
||||||
const expectedValuesKeys = Object.getOwnPropertyNames(expectedValues).sort();
|
|
||||||
|
|
||||||
assertEqArray(nameValuesKeys, expectedValuesKeys);
|
|
||||||
|
|
||||||
for (let key of expectedValuesKeys)
|
|
||||||
assertEq(nameValues[key], expectedValues[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
addIntlExtras(Intl);
|
|
||||||
|
|
||||||
let gDN = Intl.getDisplayNames;
|
|
||||||
|
|
||||||
assertEq(gDN.length, 2);
|
|
||||||
|
|
||||||
checkDisplayNames(gDN('en-US', {
|
|
||||||
}), {
|
|
||||||
locale: 'en-US',
|
|
||||||
style: 'long',
|
|
||||||
values: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
checkDisplayNames(gDN('en-US', {
|
|
||||||
keys: [
|
|
||||||
'dates/gregorian/weekdays/wednesday'
|
|
||||||
],
|
|
||||||
style: 'narrow'
|
|
||||||
}), {
|
|
||||||
locale: 'en-US',
|
|
||||||
style: 'narrow',
|
|
||||||
values: {
|
|
||||||
'dates/gregorian/weekdays/wednesday': 'W'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
checkDisplayNames(gDN('en-US', {
|
|
||||||
keys: [
|
|
||||||
'dates/fields/year',
|
|
||||||
'dates/fields/month',
|
|
||||||
'dates/fields/week',
|
|
||||||
'dates/fields/day',
|
|
||||||
'dates/gregorian/months/january',
|
|
||||||
'dates/gregorian/months/february',
|
|
||||||
'dates/gregorian/months/march',
|
|
||||||
'dates/gregorian/weekdays/tuesday'
|
|
||||||
]
|
|
||||||
}), {
|
|
||||||
locale: 'en-US',
|
|
||||||
style: 'long',
|
|
||||||
values: {
|
|
||||||
'dates/fields/year': 'year',
|
|
||||||
'dates/fields/month': 'month',
|
|
||||||
'dates/fields/week': 'week',
|
|
||||||
'dates/fields/day': 'day',
|
|
||||||
'dates/gregorian/months/january': 'January',
|
|
||||||
'dates/gregorian/months/february': 'February',
|
|
||||||
'dates/gregorian/months/march': 'March',
|
|
||||||
'dates/gregorian/weekdays/tuesday': 'Tuesday',
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
checkDisplayNames(gDN('fr', {
|
|
||||||
keys: [
|
|
||||||
'dates/fields/year',
|
|
||||||
'dates/fields/day',
|
|
||||||
'dates/gregorian/months/october',
|
|
||||||
'dates/gregorian/weekdays/saturday',
|
|
||||||
'dates/gregorian/dayperiods/pm'
|
|
||||||
]
|
|
||||||
}), {
|
|
||||||
locale: 'fr',
|
|
||||||
style: 'long',
|
|
||||||
values: {
|
|
||||||
'dates/fields/year': 'année',
|
|
||||||
'dates/fields/day': 'jour',
|
|
||||||
'dates/gregorian/months/october': 'octobre',
|
|
||||||
'dates/gregorian/weekdays/saturday': 'samedi',
|
|
||||||
'dates/gregorian/dayperiods/pm': 'PM'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
checkDisplayNames(gDN('it', {
|
|
||||||
style: 'short',
|
|
||||||
keys: [
|
|
||||||
'dates/gregorian/weekdays/thursday',
|
|
||||||
'dates/gregorian/months/august',
|
|
||||||
'dates/gregorian/dayperiods/am',
|
|
||||||
'dates/fields/month',
|
|
||||||
]
|
|
||||||
}), {
|
|
||||||
locale: 'it',
|
|
||||||
style: 'short',
|
|
||||||
values: {
|
|
||||||
'dates/gregorian/weekdays/thursday': 'gio',
|
|
||||||
'dates/gregorian/months/august': 'ago',
|
|
||||||
'dates/gregorian/dayperiods/am': 'AM',
|
|
||||||
'dates/fields/month': 'mese'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
checkDisplayNames(gDN('ar', {
|
|
||||||
style: 'long',
|
|
||||||
keys: [
|
|
||||||
'dates/gregorian/weekdays/thursday',
|
|
||||||
'dates/gregorian/months/august',
|
|
||||||
'dates/gregorian/dayperiods/am',
|
|
||||||
'dates/fields/month',
|
|
||||||
]
|
|
||||||
}), {
|
|
||||||
locale: 'ar',
|
|
||||||
style: 'long',
|
|
||||||
values: {
|
|
||||||
'dates/gregorian/weekdays/thursday': 'الخميس',
|
|
||||||
'dates/gregorian/months/august': 'أغسطس',
|
|
||||||
'dates/gregorian/dayperiods/am': 'ص',
|
|
||||||
'dates/fields/month': 'الشهر'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Invalid input */
|
|
||||||
|
|
||||||
assertThrowsInstanceOf(() => {
|
|
||||||
gDN('en-US', {
|
|
||||||
style: '',
|
|
||||||
keys: [
|
|
||||||
'dates/gregorian/weekdays/thursday',
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}, RangeError);
|
|
||||||
|
|
||||||
assertThrowsInstanceOf(() => {
|
|
||||||
gDN('en-US', {
|
|
||||||
style: 'bogus',
|
|
||||||
keys: [
|
|
||||||
'dates/gregorian/weekdays/thursday',
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}, RangeError);
|
|
||||||
|
|
||||||
assertThrowsInstanceOf(() => {
|
|
||||||
gDN('foo-X', {
|
|
||||||
keys: [
|
|
||||||
'dates/gregorian/weekdays/thursday',
|
|
||||||
]
|
|
||||||
});
|
|
||||||
}, RangeError);
|
|
||||||
|
|
||||||
const typeErrorKeys = [
|
|
||||||
null,
|
|
||||||
'string',
|
|
||||||
Symbol.iterator,
|
|
||||||
15,
|
|
||||||
1,
|
|
||||||
3.7,
|
|
||||||
NaN,
|
|
||||||
Infinity
|
|
||||||
];
|
|
||||||
|
|
||||||
for (let keys of typeErrorKeys) {
|
|
||||||
assertThrowsInstanceOf(() => {
|
|
||||||
gDN('en-US', {
|
|
||||||
keys
|
|
||||||
});
|
|
||||||
}, TypeError);
|
|
||||||
}
|
|
||||||
|
|
||||||
const rangeErrorKeys = [
|
|
||||||
[''],
|
|
||||||
['foo'],
|
|
||||||
['dates/foo'],
|
|
||||||
['/dates/foo'],
|
|
||||||
['dates/foo/foo'],
|
|
||||||
['dates/fields'],
|
|
||||||
['dates/fields/'],
|
|
||||||
['dates/fields/foo'],
|
|
||||||
['dates/fields/foo/month'],
|
|
||||||
['/dates/foo/faa/bar/baz'],
|
|
||||||
['dates///bar/baz'],
|
|
||||||
['dates/gregorian'],
|
|
||||||
['dates/gregorian/'],
|
|
||||||
['dates/gregorian/foo'],
|
|
||||||
['dates/gregorian/months'],
|
|
||||||
['dates/gregorian/months/foo'],
|
|
||||||
['dates/gregorian/weekdays'],
|
|
||||||
['dates/gregorian/weekdays/foo'],
|
|
||||||
['dates/gregorian/dayperiods'],
|
|
||||||
['dates/gregorian/dayperiods/foo'],
|
|
||||||
['dates/gregorian/months/الشهر'],
|
|
||||||
[3],
|
|
||||||
[null],
|
|
||||||
['d', 'a', 't', 'e', 's'],
|
|
||||||
['datesEXTRA'],
|
|
||||||
['dates/fieldsEXTRA'],
|
|
||||||
['dates/gregorianEXTRA'],
|
|
||||||
['dates/gregorian/monthsEXTRA'],
|
|
||||||
['dates/gregorian/weekdaysEXTRA'],
|
|
||||||
['dates/fields/dayperiods/amEXTRA'],
|
|
||||||
['dates/gregori\u1161n/months/january'],
|
|
||||||
["dates/fields/year/"],
|
|
||||||
["dates/fields/year\0"],
|
|
||||||
["dates/fields/month/"],
|
|
||||||
["dates/fields/month\0"],
|
|
||||||
["dates/fields/week/"],
|
|
||||||
["dates/fields/week\0"],
|
|
||||||
["dates/fields/day/"],
|
|
||||||
["dates/fields/day\0"],
|
|
||||||
["dates/gregorian/months/january/"],
|
|
||||||
["dates/gregorian/months/january\0"],
|
|
||||||
["dates/gregorian/weekdays/saturday/"],
|
|
||||||
["dates/gregorian/weekdays/saturday\0"],
|
|
||||||
["dates/gregorian/dayperiods/am/"],
|
|
||||||
["dates/gregorian/dayperiods/am\0"],
|
|
||||||
["dates/fields/months/january/"],
|
|
||||||
["dates/fields/months/january\0"],
|
|
||||||
];
|
|
||||||
|
|
||||||
for (let keys of rangeErrorKeys) {
|
|
||||||
assertThrowsInstanceOf(() => {
|
|
||||||
gDN('en-US', {
|
|
||||||
keys
|
|
||||||
});
|
|
||||||
}, RangeError);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof reportCompare === 'function')
|
|
||||||
reportCompare(0, 0);
|
|
|
@ -2364,7 +2364,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||||
JS_FN("intl_Collator", intl_Collator, 2, 0),
|
JS_FN("intl_Collator", intl_Collator, 2, 0),
|
||||||
JS_FN("intl_CompareStrings", intl_CompareStrings, 3, 0),
|
JS_FN("intl_CompareStrings", intl_CompareStrings, 3, 0),
|
||||||
JS_FN("intl_ComputeDisplayName", intl_ComputeDisplayName, 6, 0),
|
JS_FN("intl_ComputeDisplayName", intl_ComputeDisplayName, 6, 0),
|
||||||
JS_FN("intl_ComputeDisplayNames", intl_ComputeDisplayNames, 3, 0),
|
|
||||||
JS_FN("intl_DateTimeFormat", intl_DateTimeFormat, 2, 0),
|
JS_FN("intl_DateTimeFormat", intl_DateTimeFormat, 2, 0),
|
||||||
JS_FN("intl_FormatDateTime", intl_FormatDateTime, 2, 0),
|
JS_FN("intl_FormatDateTime", intl_FormatDateTime, 2, 0),
|
||||||
JS_FN("intl_FormatDateTimeRange", intl_FormatDateTimeRange, 4, 0),
|
JS_FN("intl_FormatDateTimeRange", intl_FormatDateTimeRange, 4, 0),
|
||||||
|
|
|
@ -49,15 +49,6 @@ MozIntlHelper::AddGetCalendarInfo(JS::Handle<JS::Value> val, JSContext* cx) {
|
||||||
return AddFunctions(cx, val, funcs);
|
return AddFunctions(cx, val, funcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
MozIntlHelper::AddGetDisplayNames(JS::Handle<JS::Value> val, JSContext* cx) {
|
|
||||||
static const JSFunctionSpec funcs[] = {
|
|
||||||
JS_SELF_HOSTED_FN("getDisplayNames", "Intl_getDisplayNames", 2, 0),
|
|
||||||
JS_FS_END};
|
|
||||||
|
|
||||||
return AddFunctions(cx, val, funcs);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
MozIntlHelper::AddDateTimeFormatConstructor(JS::Handle<JS::Value> val,
|
MozIntlHelper::AddDateTimeFormatConstructor(JS::Handle<JS::Value> val,
|
||||||
JSContext* cx) {
|
JSContext* cx) {
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
interface mozIMozIntlHelper : nsISupports
|
interface mozIMozIntlHelper : nsISupports
|
||||||
{
|
{
|
||||||
[implicit_jscontext] void addGetCalendarInfo(in jsval intlObject);
|
[implicit_jscontext] void addGetCalendarInfo(in jsval intlObject);
|
||||||
[implicit_jscontext] void addGetDisplayNames(in jsval intlObject);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a MozDateTimeFormat contructor to the given object.
|
* Adds a MozDateTimeFormat contructor to the given object.
|
||||||
|
|
|
@ -41,7 +41,6 @@ function test_cross_global(miHelper) {
|
||||||
|
|
||||||
function test_methods_presence(miHelper) {
|
function test_methods_presence(miHelper) {
|
||||||
equal(miHelper.addGetCalendarInfo instanceof Function, true);
|
equal(miHelper.addGetCalendarInfo instanceof Function, true);
|
||||||
equal(miHelper.addGetDisplayNames instanceof Function, true);
|
|
||||||
equal(miHelper.addDateTimeFormatConstructor instanceof Function, true);
|
equal(miHelper.addDateTimeFormatConstructor instanceof Function, true);
|
||||||
equal(miHelper.addDisplayNamesConstructor instanceof Function, true);
|
equal(miHelper.addDisplayNamesConstructor instanceof Function, true);
|
||||||
|
|
||||||
|
@ -50,9 +49,6 @@ function test_methods_presence(miHelper) {
|
||||||
miHelper.addGetCalendarInfo(x);
|
miHelper.addGetCalendarInfo(x);
|
||||||
equal(x.getCalendarInfo instanceof Function, true);
|
equal(x.getCalendarInfo instanceof Function, true);
|
||||||
|
|
||||||
miHelper.addGetDisplayNames(x);
|
|
||||||
equal(x.getDisplayNames instanceof Function, true);
|
|
||||||
|
|
||||||
miHelper.addDateTimeFormatConstructor(x);
|
miHelper.addDateTimeFormatConstructor(x);
|
||||||
equal(x.DateTimeFormat instanceof Function, true);
|
equal(x.DateTimeFormat instanceof Function, true);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче