summaryrefslogtreecommitdiffstats
path: root/js/src/builtin
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin')
-rw-r--r--js/src/builtin/Array.js21
-rw-r--r--js/src/builtin/Intl.cpp801
-rw-r--r--js/src/builtin/Intl.h58
-rw-r--r--js/src/builtin/Intl.js478
-rw-r--r--js/src/builtin/IntlTimeZoneData.h2
-rw-r--r--js/src/builtin/Map.js6
-rw-r--r--js/src/builtin/Set.js6
-rw-r--r--js/src/builtin/String.js15
-rw-r--r--js/src/builtin/TestingFunctions.cpp34
-rw-r--r--js/src/builtin/TypedArray.js8
10 files changed, 514 insertions, 915 deletions
diff --git a/js/src/builtin/Array.js b/js/src/builtin/Array.js
index 45f90a7b8..30e6fb35f 100644
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -711,13 +711,14 @@ function CreateArrayIterator(obj, kind) {
// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%.next
function ArrayIteratorNext() {
// Step 1-3.
- if (!IsObject(this) || !IsArrayIterator(this)) {
+ var obj;
+ if (!IsObject(this) || (obj = GuardToArrayIterator(this)) === null) {
return callFunction(CallArrayIteratorMethodIfWrapped, this,
"ArrayIteratorNext");
}
// Step 4.
- var a = UnsafeGetReservedSlot(this, ITERATOR_SLOT_TARGET);
+ var a = UnsafeGetReservedSlot(obj, ITERATOR_SLOT_TARGET);
var result = { value: undefined, done: false };
// Step 5.
@@ -728,10 +729,10 @@ function ArrayIteratorNext() {
// Step 6.
// The index might not be an integer, so we have to do a generic get here.
- var index = UnsafeGetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX);
+ var index = UnsafeGetReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX);
// Step 7.
- var itemKind = UnsafeGetInt32FromReservedSlot(this, ITERATOR_SLOT_ITEM_KIND);
+ var itemKind = UnsafeGetInt32FromReservedSlot(obj, ITERATOR_SLOT_ITEM_KIND);
// Step 8-9.
var len = IsPossiblyWrappedTypedArray(a)
@@ -740,13 +741,13 @@ function ArrayIteratorNext() {
// Step 10.
if (index >= len) {
- UnsafeSetReservedSlot(this, ITERATOR_SLOT_TARGET, null);
+ UnsafeSetReservedSlot(obj, ITERATOR_SLOT_TARGET, null);
result.done = true;
return result;
}
// Step 11.
- UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + 1);
+ UnsafeSetReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX, index + 1);
// Step 16.
if (itemKind === ITEM_KIND_VALUE) {
@@ -900,11 +901,7 @@ function ArrayToLocaleString(locales, options) {
if (firstElement === undefined || firstElement === null) {
R = "";
} else {
-#if EXPOSE_INTL_API
R = ToString(callContentFunction(firstElement.toLocaleString, firstElement, locales, options));
-#else
- R = ToString(callContentFunction(firstElement.toLocaleString, firstElement));
-#endif
}
// Step 3 (reordered).
@@ -919,11 +916,7 @@ function ArrayToLocaleString(locales, options) {
// Steps 9.a, 9.c-e.
R += separator;
if (!(nextElement === undefined || nextElement === null)) {
-#if EXPOSE_INTL_API
R += ToString(callContentFunction(nextElement.toLocaleString, nextElement, locales, options));
-#else
- R += ToString(callContentFunction(nextElement.toLocaleString, nextElement));
-#endif
}
}
diff --git a/js/src/builtin/Intl.cpp b/js/src/builtin/Intl.cpp
index 3a20c487b..71f7b58d4 100644
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -23,7 +23,6 @@
#include "jsobj.h"
#include "builtin/IntlTimeZoneData.h"
-#if ENABLE_INTL_API
#include "unicode/ucal.h"
#include "unicode/ucol.h"
#include "unicode/udat.h"
@@ -32,7 +31,6 @@
#include "unicode/unum.h"
#include "unicode/unumsys.h"
#include "unicode/ustring.h"
-#endif
#include "vm/DateTime.h"
#include "vm/GlobalObject.h"
#include "vm/Interpreter.h"
@@ -60,512 +58,6 @@ using mozilla::PodCopy;
* http://userguide.icu-project.org/design#TOC-Error-Handling
*/
-
-/******************** ICU stubs ********************/
-
-#if !ENABLE_INTL_API
-
-/*
- * When the Internationalization API isn't enabled, we also shouldn't link
- * against ICU. However, we still want to compile this code in order to prevent
- * bit rot. The following stub implementations for ICU functions make this
- * possible. The functions using them should never be called, so they assert
- * and return error codes. Signatures adapted from ICU header files locid.h,
- * numsys.h, ucal.h, ucol.h, udat.h, udatpg.h, uenum.h, unum.h; see the ICU
- * directory for license.
- */
-
-typedef bool UBool;
-typedef char16_t UChar;
-typedef double UDate;
-
-enum UErrorCode {
- U_ZERO_ERROR,
- U_BUFFER_OVERFLOW_ERROR,
-};
-
-static inline UBool
-U_FAILURE(UErrorCode code)
-{
- MOZ_CRASH("U_FAILURE: Intl API disabled");
-}
-
-inline const UChar*
-Char16ToUChar(const char16_t* chars)
-{
- MOZ_CRASH("Char16ToUChar: Intl API disabled");
-}
-
-inline UChar*
-Char16ToUChar(char16_t* chars)
-{
- MOZ_CRASH("Char16ToUChar: Intl API disabled");
-}
-
-static int32_t
-u_strlen(const UChar* s)
-{
- MOZ_CRASH("u_strlen: Intl API disabled");
-}
-
-struct UEnumeration;
-
-static int32_t
-uenum_count(UEnumeration* en, UErrorCode* status)
-{
- MOZ_CRASH("uenum_count: Intl API disabled");
-}
-
-static const char*
-uenum_next(UEnumeration* en, int32_t* resultLength, UErrorCode* status)
-{
- MOZ_CRASH("uenum_next: Intl API disabled");
-}
-
-static void
-uenum_close(UEnumeration* en)
-{
- MOZ_CRASH("uenum_close: Intl API disabled");
-}
-
-struct UCollator;
-
-enum UColAttribute {
- UCOL_ALTERNATE_HANDLING,
- UCOL_CASE_FIRST,
- UCOL_CASE_LEVEL,
- UCOL_NORMALIZATION_MODE,
- UCOL_STRENGTH,
- UCOL_NUMERIC_COLLATION,
-};
-
-enum UColAttributeValue {
- UCOL_DEFAULT = -1,
- UCOL_PRIMARY = 0,
- UCOL_SECONDARY = 1,
- UCOL_TERTIARY = 2,
- UCOL_OFF = 16,
- UCOL_ON = 17,
- UCOL_SHIFTED = 20,
- UCOL_LOWER_FIRST = 24,
- UCOL_UPPER_FIRST = 25,
-};
-
-enum UCollationResult {
- UCOL_EQUAL = 0,
- UCOL_GREATER = 1,
- UCOL_LESS = -1
-};
-
-static int32_t
-ucol_countAvailable()
-{
- MOZ_CRASH("ucol_countAvailable: Intl API disabled");
-}
-
-static const char*
-ucol_getAvailable(int32_t localeIndex)
-{
- MOZ_CRASH("ucol_getAvailable: Intl API disabled");
-}
-
-static UCollator*
-ucol_open(const char* loc, UErrorCode* status)
-{
- MOZ_CRASH("ucol_open: Intl API disabled");
-}
-
-static void
-ucol_setAttribute(UCollator* coll, UColAttribute attr, UColAttributeValue value, UErrorCode* status)
-{
- MOZ_CRASH("ucol_setAttribute: Intl API disabled");
-}
-
-static UCollationResult
-ucol_strcoll(const UCollator* coll, const UChar* source, int32_t sourceLength,
- const UChar* target, int32_t targetLength)
-{
- MOZ_CRASH("ucol_strcoll: Intl API disabled");
-}
-
-static void
-ucol_close(UCollator* coll)
-{
- MOZ_CRASH("ucol_close: Intl API disabled");
-}
-
-static UEnumeration*
-ucol_getKeywordValuesForLocale(const char* key, const char* locale, UBool commonlyUsed,
- UErrorCode* status)
-{
- MOZ_CRASH("ucol_getKeywordValuesForLocale: Intl API disabled");
-}
-
-struct UParseError;
-struct UFieldPosition;
-struct UFieldPositionIterator;
-typedef void* UNumberFormat;
-
-enum UNumberFormatStyle {
- UNUM_DECIMAL = 1,
- UNUM_CURRENCY,
- UNUM_PERCENT,
- UNUM_CURRENCY_ISO,
- UNUM_CURRENCY_PLURAL,
-};
-
-enum UNumberFormatRoundingMode {
- UNUM_ROUND_HALFUP,
-};
-
-enum UNumberFormatAttribute {
- UNUM_GROUPING_USED,
- UNUM_MIN_INTEGER_DIGITS,
- UNUM_MAX_FRACTION_DIGITS,
- UNUM_MIN_FRACTION_DIGITS,
- UNUM_ROUNDING_MODE,
- UNUM_SIGNIFICANT_DIGITS_USED,
- UNUM_MIN_SIGNIFICANT_DIGITS,
- UNUM_MAX_SIGNIFICANT_DIGITS,
-};
-
-enum UNumberFormatTextAttribute {
- UNUM_CURRENCY_CODE,
-};
-
-static int32_t
-unum_countAvailable()
-{
- MOZ_CRASH("unum_countAvailable: Intl API disabled");
-}
-
-static const char*
-unum_getAvailable(int32_t localeIndex)
-{
- MOZ_CRASH("unum_getAvailable: Intl API disabled");
-}
-
-static UNumberFormat*
-unum_open(UNumberFormatStyle style, const UChar* pattern, int32_t patternLength,
- const char* locale, UParseError* parseErr, UErrorCode* status)
-{
- MOZ_CRASH("unum_open: Intl API disabled");
-}
-
-static void
-unum_setAttribute(UNumberFormat* fmt, UNumberFormatAttribute attr, int32_t newValue)
-{
- MOZ_CRASH("unum_setAttribute: Intl API disabled");
-}
-
-static int32_t
-unum_formatDouble(const UNumberFormat* fmt, double number, UChar* result,
- int32_t resultLength, UFieldPosition* pos, UErrorCode* status)
-{
- MOZ_CRASH("unum_formatDouble: Intl API disabled");
-}
-
-static void
-unum_close(UNumberFormat* fmt)
-{
- MOZ_CRASH("unum_close: Intl API disabled");
-}
-
-static void
-unum_setTextAttribute(UNumberFormat* fmt, UNumberFormatTextAttribute tag, const UChar* newValue,
- int32_t newValueLength, UErrorCode* status)
-{
- MOZ_CRASH("unum_setTextAttribute: Intl API disabled");
-}
-
-typedef void* UNumberingSystem;
-
-static UNumberingSystem*
-unumsys_open(const char* locale, UErrorCode* status)
-{
- MOZ_CRASH("unumsys_open: Intl API disabled");
-}
-
-static const char*
-unumsys_getName(const UNumberingSystem* unumsys)
-{
- MOZ_CRASH("unumsys_getName: Intl API disabled");
-}
-
-static void
-unumsys_close(UNumberingSystem* unumsys)
-{
- MOZ_CRASH("unumsys_close: Intl API disabled");
-}
-
-typedef void* UCalendar;
-
-enum UCalendarType {
- UCAL_TRADITIONAL,
- UCAL_DEFAULT = UCAL_TRADITIONAL,
- UCAL_GREGORIAN
-};
-
-enum UCalendarAttribute {
- UCAL_FIRST_DAY_OF_WEEK,
- UCAL_MINIMAL_DAYS_IN_FIRST_WEEK
-};
-
-enum UCalendarDaysOfWeek {
- UCAL_SUNDAY,
- UCAL_MONDAY,
- UCAL_TUESDAY,
- UCAL_WEDNESDAY,
- UCAL_THURSDAY,
- UCAL_FRIDAY,
- UCAL_SATURDAY
-};
-
-enum UCalendarWeekdayType {
- UCAL_WEEKDAY,
- UCAL_WEEKEND,
- UCAL_WEEKEND_ONSET,
- UCAL_WEEKEND_CEASE
-};
-
-enum UCalendarDateFields {
- UCAL_ERA,
- UCAL_YEAR,
- UCAL_MONTH,
- UCAL_WEEK_OF_YEAR,
- UCAL_WEEK_OF_MONTH,
- UCAL_DATE,
- UCAL_DAY_OF_YEAR,
- UCAL_DAY_OF_WEEK,
- UCAL_DAY_OF_WEEK_IN_MONTH,
- UCAL_AM_PM,
- UCAL_HOUR,
- UCAL_HOUR_OF_DAY,
- UCAL_MINUTE,
- UCAL_SECOND,
- UCAL_MILLISECOND,
- UCAL_ZONE_OFFSET,
- UCAL_DST_OFFSET,
- UCAL_YEAR_WOY,
- UCAL_DOW_LOCAL,
- UCAL_EXTENDED_YEAR,
- UCAL_JULIAN_DAY,
- UCAL_MILLISECONDS_IN_DAY,
- UCAL_IS_LEAP_MONTH,
- UCAL_FIELD_COUNT,
- UCAL_DAY_OF_MONTH = UCAL_DATE
-};
-
-static UCalendar*
-ucal_open(const UChar* zoneID, int32_t len, const char* locale,
- UCalendarType type, UErrorCode* status)
-{
- MOZ_CRASH("ucal_open: Intl API disabled");
-}
-
-static const char*
-ucal_getType(const UCalendar* cal, UErrorCode* status)
-{
- MOZ_CRASH("ucal_getType: Intl API disabled");
-}
-
-static UEnumeration*
-ucal_getKeywordValuesForLocale(const char* key, const char* locale,
- UBool commonlyUsed, UErrorCode* status)
-{
- MOZ_CRASH("ucal_getKeywordValuesForLocale: Intl API disabled");
-}
-
-static void
-ucal_close(UCalendar* cal)
-{
- MOZ_CRASH("ucal_close: Intl API disabled");
-}
-
-static UCalendarWeekdayType
-ucal_getDayOfWeekType(const UCalendar *cal, UCalendarDaysOfWeek dayOfWeek, UErrorCode* status)
-{
- MOZ_CRASH("ucal_getDayOfWeekType: Intl API disabled");
-}
-
-static int32_t
-ucal_getAttribute(const UCalendar* cal,
- UCalendarAttribute attr)
-{
- MOZ_CRASH("ucal_getAttribute: Intl API disabled");
-}
-
-static int32_t
-ucal_get(const UCalendar *cal, UCalendarDateFields field, UErrorCode *status)
-{
- MOZ_CRASH("ucal_get: Intl API disabled");
-}
-
-static UEnumeration*
-ucal_openTimeZones(UErrorCode* status)
-{
- MOZ_CRASH("ucal_openTimeZones: Intl API disabled");
-}
-
-static int32_t
-ucal_getCanonicalTimeZoneID(const UChar* id, int32_t len, UChar* result, int32_t resultCapacity,
- UBool* isSystemID, UErrorCode* status)
-{
- MOZ_CRASH("ucal_getCanonicalTimeZoneID: Intl API disabled");
-}
-
-static int32_t
-ucal_getDefaultTimeZone(UChar* result, int32_t resultCapacity, UErrorCode* status)
-{
- MOZ_CRASH("ucal_getDefaultTimeZone: Intl API disabled");
-}
-
-typedef void* UDateTimePatternGenerator;
-
-static UDateTimePatternGenerator*
-udatpg_open(const char* locale, UErrorCode* pErrorCode)
-{
- MOZ_CRASH("udatpg_open: Intl API disabled");
-}
-
-static int32_t
-udatpg_getBestPattern(UDateTimePatternGenerator* dtpg, const UChar* skeleton,
- int32_t length, UChar* bestPattern, int32_t capacity,
- UErrorCode* pErrorCode)
-{
- MOZ_CRASH("udatpg_getBestPattern: Intl API disabled");
-}
-
-static void
-udatpg_close(UDateTimePatternGenerator* dtpg)
-{
- MOZ_CRASH("udatpg_close: Intl API disabled");
-}
-
-typedef void* UCalendar;
-typedef void* UDateFormat;
-
-enum UDateFormatField {
- UDAT_ERA_FIELD = 0,
- UDAT_YEAR_FIELD = 1,
- UDAT_MONTH_FIELD = 2,
- UDAT_DATE_FIELD = 3,
- UDAT_HOUR_OF_DAY1_FIELD = 4,
- UDAT_HOUR_OF_DAY0_FIELD = 5,
- UDAT_MINUTE_FIELD = 6,
- UDAT_SECOND_FIELD = 7,
- UDAT_FRACTIONAL_SECOND_FIELD = 8,
- UDAT_DAY_OF_WEEK_FIELD = 9,
- UDAT_DAY_OF_YEAR_FIELD = 10,
- UDAT_DAY_OF_WEEK_IN_MONTH_FIELD = 11,
- UDAT_WEEK_OF_YEAR_FIELD = 12,
- UDAT_WEEK_OF_MONTH_FIELD = 13,
- UDAT_AM_PM_FIELD = 14,
- UDAT_HOUR1_FIELD = 15,
- UDAT_HOUR0_FIELD = 16,
- UDAT_TIMEZONE_FIELD = 17,
- UDAT_YEAR_WOY_FIELD = 18,
- UDAT_DOW_LOCAL_FIELD = 19,
- UDAT_EXTENDED_YEAR_FIELD = 20,
- UDAT_JULIAN_DAY_FIELD = 21,
- UDAT_MILLISECONDS_IN_DAY_FIELD = 22,
- UDAT_TIMEZONE_RFC_FIELD = 23,
- UDAT_TIMEZONE_GENERIC_FIELD = 24,
- UDAT_STANDALONE_DAY_FIELD = 25,
- UDAT_STANDALONE_MONTH_FIELD = 26,
- UDAT_QUARTER_FIELD = 27,
- UDAT_STANDALONE_QUARTER_FIELD = 28,
- UDAT_TIMEZONE_SPECIAL_FIELD = 29,
- UDAT_YEAR_NAME_FIELD = 30,
- UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD = 31,
- UDAT_TIMEZONE_ISO_FIELD = 32,
- UDAT_TIMEZONE_ISO_LOCAL_FIELD = 33,
- UDAT_RELATED_YEAR_FIELD = 34,
- UDAT_AM_PM_MIDNIGHT_NOON_FIELD = 35,
- UDAT_FLEXIBLE_DAY_PERIOD_FIELD = 36,
- UDAT_TIME_SEPARATOR_FIELD = 37,
- UDAT_FIELD_COUNT = 38
-};
-
-enum UDateFormatStyle {
- UDAT_PATTERN = -2,
- UDAT_IGNORE = UDAT_PATTERN
-};
-
-static int32_t
-udat_countAvailable()
-{
- MOZ_CRASH("udat_countAvailable: Intl API disabled");
-}
-
-static const char*
-udat_getAvailable(int32_t localeIndex)
-{
- MOZ_CRASH("udat_getAvailable: Intl API disabled");
-}
-
-static UDateFormat*
-udat_open(UDateFormatStyle timeStyle, UDateFormatStyle dateStyle, const char* locale,
- const UChar* tzID, int32_t tzIDLength, const UChar* pattern,
- int32_t patternLength, UErrorCode* status)
-{
- MOZ_CRASH("udat_open: Intl API disabled");
-}
-
-static const UCalendar*
-udat_getCalendar(const UDateFormat* fmt)
-{
- MOZ_CRASH("udat_getCalendar: Intl API disabled");
-}
-
-static void
-ucal_setGregorianChange(UCalendar* cal, UDate date, UErrorCode* pErrorCode)
-{
- MOZ_CRASH("ucal_setGregorianChange: Intl API disabled");
-}
-
-static int32_t
-udat_format(const UDateFormat* format, UDate dateToFormat, UChar* result,
- int32_t resultLength, UFieldPosition* position, UErrorCode* status)
-{
- MOZ_CRASH("udat_format: Intl API disabled");
-}
-
-static int32_t
-udat_formatForFields(const UDateFormat* format, UDate dateToFormat,
- UChar* result, int32_t resultLength, UFieldPositionIterator* fpositer,
- UErrorCode* status)
-{
- MOZ_CRASH("udat_formatForFields: Intl API disabled");
-}
-
-static UFieldPositionIterator*
-ufieldpositer_open(UErrorCode* status)
-{
- MOZ_CRASH("ufieldpositer_open: Intl API disabled");
-}
-
-static void
-ufieldpositer_close(UFieldPositionIterator* fpositer)
-{
- MOZ_CRASH("ufieldpositer_close: Intl API disabled");
-}
-
-static int32_t
-ufieldpositer_next(UFieldPositionIterator* fpositer, int32_t* beginIndex, int32_t* endIndex)
-{
- MOZ_CRASH("ufieldpositer_next: Intl API disabled");
-}
-
-static void
-udat_close(UDateFormat* format)
-{
- MOZ_CRASH("udat_close: Intl API disabled");
-}
-
-#endif
-
-
/******************** Common to Intl constructors ********************/
static bool
@@ -615,7 +107,6 @@ intl_availableLocales(JSContext* cx, CountAvailable countAvailable,
if (!locales)
return false;
-#if ENABLE_INTL_API
uint32_t count = countAvailable();
RootedValue t(cx, BooleanValue(true));
for (uint32_t i = 0; i < count; i++) {
@@ -635,7 +126,7 @@ intl_availableLocales(JSContext* cx, CountAvailable countAvailable,
return false;
}
}
-#endif
+
result.setObject(*locales);
return true;
}
@@ -2921,6 +2412,296 @@ js::intl_GetCalendarInfo(JSContext* cx, unsigned argc, Value* vp)
return true;
}
+template<size_t N>
+inline bool
+MatchPart(const char** pattern, const char (&part)[N])
+{
+ if (strncmp(*pattern, part, N - 1))
+ return false;
+
+ *pattern += N - 1;
+ return true;
+}
+
+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.
+ MOZ_ASSERT(args[0].isString());
+ // 2. Assert: style is a string.
+ MOZ_ASSERT(args[1].isString());
+ // 3. Assert: keys is an Array.
+ MOZ_ASSERT(args[2].isObject());
+
+ JSAutoByteString locale(cx, args[0].toString());
+ if (!locale)
+ return false;
+
+ JSAutoByteString style(cx, args[1].toString());
+ if (!style)
+ return false;
+
+ RootedArrayObject keys(cx, &args[2].toObject().as<ArrayObject>());
+ if (!keys)
+ return false;
+
+ // 4. Let result be ArrayCreate(0).
+ RootedArrayObject result(cx, NewDenseUnallocatedArray(cx, keys->length()));
+ if (!result)
+ return false;
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ UDateFormat* fmt =
+ udat_open(UDAT_DEFAULT, UDAT_DEFAULT, icuLocale(locale.ptr()),
+ nullptr, 0, nullptr, 0, &status);
+ if (U_FAILURE(status)) {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
+ 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.ptr()), &status);
+ if (U_FAILURE(status)) {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
+ return false;
+ }
+ ScopedICUObject<UDateTimePatternGenerator, udatpg_close> datPgToClose(dtpg);
+
+ RootedValue keyValue(cx);
+ RootedString keyValStr(cx);
+ RootedValue wordVal(cx);
+ Vector<char16_t, INITIAL_CHAR_BUFFER_SIZE> chars(cx);
+ if (!chars.resize(INITIAL_CHAR_BUFFER_SIZE))
+ return false;
+
+ // 5. For each element of keys,
+ for (uint32_t i = 0; i < keys->length(); i++) {
+ /**
+ * We iterate over keys array looking for paths that we have code
+ * branches for.
+ *
+ * For any unknown path branch, the wordVal will keep NullValue and
+ * we'll throw at the end.
+ */
+
+ if (!GetElement(cx, keys, keys, i, &keyValue))
+ return false;
+
+ JSAutoByteString pattern;
+ keyValStr = keyValue.toString();
+ if (!pattern.encodeUtf8(cx, keyValStr))
+ return false;
+
+ wordVal.setNull();
+
+ // 5.a. Perform an implementation dependent algorithm to map a key to a
+ // corresponding display name.
+ const char* pat = pattern.ptr();
+
+ if (!MatchPart(&pat, "dates")) {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ if (!MatchPart(&pat, "/")) {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ if (MatchPart(&pat, "fields")) {
+ if (!MatchPart(&pat, "/")) {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ UDateTimePatternField fieldType;
+
+ if (MatchPart(&pat, "year")) {
+ fieldType = UDATPG_YEAR_FIELD;
+ } else if (MatchPart(&pat, "month")) {
+ fieldType = UDATPG_MONTH_FIELD;
+ } else if (MatchPart(&pat, "week")) {
+ fieldType = UDATPG_WEEK_OF_YEAR_FIELD;
+ } else if (MatchPart(&pat, "day")) {
+ fieldType = UDATPG_DAY_FIELD;
+ } else {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ // This part must be the final part with no trailing data.
+ if (*pat != '\0') {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ int32_t resultSize;
+
+ const UChar* value = udatpg_getAppendItemName(dtpg, fieldType, &resultSize);
+ if (U_FAILURE(status)) {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
+ return false;
+ }
+
+ JSString* word = NewStringCopyN<CanGC>(cx, UCharToChar16(value), resultSize);
+ if (!word)
+ return false;
+
+ wordVal.setString(word);
+ } else if (MatchPart(&pat, "gregorian")) {
+ if (!MatchPart(&pat, "/")) {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ UDateFormatSymbolType symbolType;
+ int32_t index;
+
+ if (MatchPart(&pat, "months")) {
+ if (!MatchPart(&pat, "/")) {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ if (equal(style, "narrow")) {
+ symbolType = UDAT_STANDALONE_NARROW_MONTHS;
+ } else if (equal(style, "short")) {
+ symbolType = UDAT_STANDALONE_SHORT_MONTHS;
+ } else {
+ MOZ_ASSERT(equal(style, "long"));
+ symbolType = UDAT_STANDALONE_MONTHS;
+ }
+
+ if (MatchPart(&pat, "january")) {
+ index = UCAL_JANUARY;
+ } else if (MatchPart(&pat, "february")) {
+ index = UCAL_FEBRUARY;
+ } else if (MatchPart(&pat, "march")) {
+ index = UCAL_MARCH;
+ } else if (MatchPart(&pat, "april")) {
+ index = UCAL_APRIL;
+ } else if (MatchPart(&pat, "may")) {
+ index = UCAL_MAY;
+ } else if (MatchPart(&pat, "june")) {
+ index = UCAL_JUNE;
+ } else if (MatchPart(&pat, "july")) {
+ index = UCAL_JULY;
+ } else if (MatchPart(&pat, "august")) {
+ index = UCAL_AUGUST;
+ } else if (MatchPart(&pat, "september")) {
+ index = UCAL_SEPTEMBER;
+ } else if (MatchPart(&pat, "october")) {
+ index = UCAL_OCTOBER;
+ } else if (MatchPart(&pat, "november")) {
+ index = UCAL_NOVEMBER;
+ } else if (MatchPart(&pat, "december")) {
+ index = UCAL_DECEMBER;
+ } else {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+ } else if (MatchPart(&pat, "weekdays")) {
+ if (!MatchPart(&pat, "/")) {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ if (equal(style, "narrow")) {
+ symbolType = UDAT_STANDALONE_NARROW_WEEKDAYS;
+ } else if (equal(style, "short")) {
+ symbolType = UDAT_STANDALONE_SHORT_WEEKDAYS;
+ } else {
+ MOZ_ASSERT(equal(style, "long"));
+ symbolType = UDAT_STANDALONE_WEEKDAYS;
+ }
+
+ if (MatchPart(&pat, "monday")) {
+ index = UCAL_MONDAY;
+ } else if (MatchPart(&pat, "tuesday")) {
+ index = UCAL_TUESDAY;
+ } else if (MatchPart(&pat, "wednesday")) {
+ index = UCAL_WEDNESDAY;
+ } else if (MatchPart(&pat, "thursday")) {
+ index = UCAL_THURSDAY;
+ } else if (MatchPart(&pat, "friday")) {
+ index = UCAL_FRIDAY;
+ } else if (MatchPart(&pat, "saturday")) {
+ index = UCAL_SATURDAY;
+ } else if (MatchPart(&pat, "sunday")) {
+ index = UCAL_SUNDAY;
+ } else {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+ } else if (MatchPart(&pat, "dayperiods")) {
+ if (!MatchPart(&pat, "/")) {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ symbolType = UDAT_AM_PMS;
+
+ if (MatchPart(&pat, "am")) {
+ index = UCAL_AM;
+ } else if (MatchPart(&pat, "pm")) {
+ index = UCAL_PM;
+ } else {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+ } else {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ // This part must be the final part with no trailing data.
+ if (*pat != '\0') {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ int32_t resultSize =
+ udat_getSymbols(fmt, symbolType, index, Char16ToUChar(chars.begin()),
+ INITIAL_CHAR_BUFFER_SIZE, &status);
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ if (!chars.resize(resultSize))
+ return false;
+ status = U_ZERO_ERROR;
+ udat_getSymbols(fmt, symbolType, index, Char16ToUChar(chars.begin()),
+ resultSize, &status);
+ }
+ if (U_FAILURE(status)) {
+ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INTERNAL_INTL_ERROR);
+ return false;
+ }
+
+ JSString* word = NewStringCopyN<CanGC>(cx, chars.begin(), resultSize);
+ if (!word)
+ return false;
+
+ wordVal.setString(word);
+ } else {
+ JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_INVALID_KEY, pattern.ptr());
+ return false;
+ }
+
+ MOZ_ASSERT(wordVal.isString());
+
+ // 5.b. Append the result string to result.
+ if (!DefineElement(cx, result, i, wordVal))
+ return false;
+ }
+
+ // 6. Return result.
+ args.rval().setObject(*result);
+ return true;
+}
+
/******************** Intl ********************/
const Class js::IntlClass = {
diff --git a/js/src/builtin/Intl.h b/js/src/builtin/Intl.h
index 54764605b..9a1e44913 100644
--- a/js/src/builtin/Intl.h
+++ b/js/src/builtin/Intl.h
@@ -16,9 +16,7 @@
#include "js/GCAPI.h"
#include "js/GCHashTable.h"
-#if ENABLE_INTL_API
#include "unicode/utypes.h"
-#endif
/*
* The Intl module specified by standard ECMA-402,
@@ -387,7 +385,48 @@ intl_FormatDateTime(JSContext* cx, unsigned argc, Value* vp);
extern MOZ_MUST_USE bool
intl_GetCalendarInfo(JSContext* cx, unsigned argc, Value* vp);
-#if ENABLE_INTL_API
+/**
+ * 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'
+ * ]
+ */
+extern MOZ_MUST_USE bool
+intl_ComputeDisplayNames(JSContext* cx, unsigned argc, Value* vp);
+
/**
* Cast char16_t* strings to UChar* strings used by ICU.
*/
@@ -402,7 +441,18 @@ Char16ToUChar(char16_t* chars)
{
return reinterpret_cast<UChar*>(chars);
}
-#endif // ENABLE_INTL_API
+
+inline char16_t*
+UCharToChar16(UChar* chars)
+{
+ return reinterpret_cast<char16_t*>(chars);
+}
+
+inline const char16_t*
+UCharToChar16(const UChar* chars)
+{
+ return reinterpret_cast<const char16_t*>(chars);
+}
} // namespace js
diff --git a/js/src/builtin/Intl.js b/js/src/builtin/Intl.js
index 37c87365b..6391c3e70 100644
--- a/js/src/builtin/Intl.js
+++ b/js/src/builtin/Intl.js
@@ -21,9 +21,6 @@
intl_availableCalendars: false,
intl_patternForSkeleton: false,
intl_FormatDateTime: false,
- intl_SelectPluralRule: false,
- intl_GetPluralCategories: false,
- intl_GetCalendarInfo: false,
*/
/*
@@ -860,7 +857,6 @@ function BestAvailableLocaleIgnoringDefault(availableLocales, locale) {
return BestAvailableLocaleHelper(availableLocales, locale, false);
}
-var noRelevantExtensionKeys = [];
/**
* Compares a BCP 47 language priority list against the set of locales in
@@ -1188,10 +1184,9 @@ function GetOption(options, property, type, values, fallback) {
* Spec: ECMAScript Internationalization API Specification, 9.2.10.
*/
function GetNumberOption(options, property, minimum, maximum, fallback) {
- assert(typeof minimum === "number" && (minimum | 0) === minimum, "GetNumberOption");
- assert(typeof maximum === "number" && (maximum | 0) === maximum, "GetNumberOption");
- assert(typeof fallback === "number" && (fallback | 0) === fallback, "GetNumberOption");
- assert(minimum <= fallback && fallback <= maximum, "GetNumberOption");
+ assert(typeof minimum === "number", "GetNumberOption");
+ assert(typeof maximum === "number", "GetNumberOption");
+ assert(fallback === undefined || (fallback >= minimum && fallback <= maximum), "GetNumberOption");
// Step 1.
var value = options[property];
@@ -1201,10 +1196,7 @@ function GetNumberOption(options, property, minimum, maximum, fallback) {
value = ToNumber(value);
if (Number_isNaN(value) || value < minimum || value > maximum)
ThrowRangeError(JSMSG_INVALID_DIGITS_VALUE, value);
-
- // Apply bitwise-or to convert -0 to +0 per ES2017, 5.2 and to ensure
- // the result is an int32 value.
- return std_Math_floor(value) | 0;
+ return std_Math_floor(value);
}
// Step 3.
@@ -1278,9 +1270,7 @@ function initializeIntlObject(obj) {
function setLazyData(internals, type, lazyData)
{
assert(internals.type === "partial", "can't set lazy data for anything but a newborn");
- assert(type === "Collator" || type === "DateTimeFormat" ||
- type == "NumberFormat" || type === "PluralRules",
- "bad type");
+ assert(type === "Collator" || type === "DateTimeFormat" || type == "NumberFormat", "bad type");
assert(IsObject(lazyData), "non-object lazy data");
// Set in reverse order so that the .type change is a barrier.
@@ -1330,9 +1320,7 @@ function isInitializedIntlObject(obj) {
if (IsObject(internals)) {
assert(callFunction(std_Object_hasOwnProperty, internals, "type"), "missing type");
var type = internals.type;
- assert(type === "partial" || type === "Collator" ||
- type === "DateTimeFormat" || type === "NumberFormat" || type === "PluralRules",
- "unexpected type");
+ assert(type === "partial" || type === "Collator" || type === "DateTimeFormat" || type === "NumberFormat", "unexpected type");
assert(callFunction(std_Object_hasOwnProperty, internals, "lazyData"), "missing lazyData");
assert(callFunction(std_Object_hasOwnProperty, internals, "internalProps"), "missing internalProps");
} else {
@@ -1389,8 +1377,6 @@ function getInternals(obj)
internalProps = resolveCollatorInternals(lazyData)
else if (type === "DateTimeFormat")
internalProps = resolveDateTimeFormatInternals(lazyData)
- else if (type === "PluralRules")
- internalProps = resolvePluralRulesInternals(lazyData)
else
internalProps = resolveNumberFormatInternals(lazyData);
setInternalProperties(internals, internalProps);
@@ -1722,7 +1708,6 @@ function Intl_Collator_compare_get() {
// Step 2.
return internals.boundCompare;
}
-_SetCanonicalName(Intl_Collator_compare_get, "get compare");
/**
@@ -1791,37 +1776,45 @@ function resolveNumberFormatInternals(lazyNumberFormatData) {
// Step 6.
var opt = lazyNumberFormatData.opt;
+ // Compute effective locale.
+ // Step 9.
var NumberFormat = numberFormatInternalProperties;
- // Step 9.
+ // Step 10.
var localeData = NumberFormat.localeData;
- // Step 10.
+ // Step 11.
var r = ResolveLocale(callFunction(NumberFormat.availableLocales, NumberFormat),
lazyNumberFormatData.requestedLocales,
lazyNumberFormatData.opt,
NumberFormat.relevantExtensionKeys,
localeData);
- // Steps 11-12. (Step 13 is not relevant to our implementation.)
+ // Steps 12-13. (Step 14 is not relevant to our implementation.)
internalProps.locale = r.locale;
internalProps.numberingSystem = r.nu;
// Compute formatting options.
- // Step 15.
- var style = lazyNumberFormatData.style;
- internalProps.style = style;
+ // Step 16.
+ var s = lazyNumberFormatData.style;
+ internalProps.style = s;
- // Steps 19, 21.
- if (style === "currency") {
+ // Steps 20, 22.
+ if (s === "currency") {
internalProps.currency = lazyNumberFormatData.currency;
internalProps.currencyDisplay = lazyNumberFormatData.currencyDisplay;
}
+ // Step 24.
internalProps.minimumIntegerDigits = lazyNumberFormatData.minimumIntegerDigits;
+
+ // Steps 27.
internalProps.minimumFractionDigits = lazyNumberFormatData.minimumFractionDigits;
+
+ // Step 30.
internalProps.maximumFractionDigits = lazyNumberFormatData.maximumFractionDigits;
+ // Step 33.
if ("minimumSignificantDigits" in lazyNumberFormatData) {
// Note: Intl.NumberFormat.prototype.resolvedOptions() exposes the
// actual presence (versus undefined-ness) of these properties.
@@ -1830,10 +1823,10 @@ function resolveNumberFormatInternals(lazyNumberFormatData) {
internalProps.maximumSignificantDigits = lazyNumberFormatData.maximumSignificantDigits;
}
- // Step 27.
+ // Step 35.
internalProps.useGrouping = lazyNumberFormatData.useGrouping;
- // Step 34.
+ // Step 42.
internalProps.boundFormat = undefined;
// The caller is responsible for associating |internalProps| with the right
@@ -1861,44 +1854,6 @@ function getNumberFormatInternals(obj, methodName) {
return internalProps;
}
-/**
- * Applies digit options used for number formatting onto the intl object.
- *
- * Spec: ECMAScript Internationalization API Specification, 11.1.1.
- */
-function SetNumberFormatDigitOptions(lazyData, options, mnfdDefault, mxfdDefault) {
- // We skip Step 1 because we set the properties on a lazyData object.
-
- // Step 2-3.
- assert(IsObject(options), "SetNumberFormatDigitOptions");
- assert(typeof mnfdDefault === "number", "SetNumberFormatDigitOptions");
- assert(typeof mxfdDefault === "number", "SetNumberFormatDigitOptions");
- assert(mnfdDefault <= mxfdDefault, "SetNumberFormatDigitOptions");
-
- // Steps 4-6.
- const mnid = GetNumberOption(options, "minimumIntegerDigits", 1, 21, 1);
- const mnfd = GetNumberOption(options, "minimumFractionDigits", 0, 20, mnfdDefault);
- const mxfdActualDefault = std_Math_max(mnfd, mxfdDefault);
- const mxfd = GetNumberOption(options, "maximumFractionDigits", mnfd, 20, mxfdActualDefault);
-
- // Steps 7-8.
- let mnsd = options.minimumSignificantDigits;
- let mxsd = options.maximumSignificantDigits;
-
- // Steps 9-11.
- lazyData.minimumIntegerDigits = mnid;
- lazyData.minimumFractionDigits = mnfd;
- lazyData.maximumFractionDigits = mxfd;
-
- // Step 12.
- if (mnsd !== undefined || mxsd !== undefined) {
- mnsd = GetNumberOption(options, "minimumSignificantDigits", 1, 21, 1);
- mxsd = GetNumberOption(options, "maximumSignificantDigits", mnsd, 21, 21);
- lazyData.minimumSignificantDigits = mnsd;
- lazyData.maximumSignificantDigits = mxsd;
- }
-}
-
/**
* Initializes an object as a NumberFormat.
@@ -1948,7 +1903,7 @@ function InitializeNumberFormat(numberFormat, locales, options) {
// }
//
// Note that lazy data is only installed as a final step of initialization,
- // so every NumberFormat lazy data object has *all* these properties, never a
+ // so every Collator lazy data object has *all* these properties, never a
// subset of them.
var lazyNumberFormatData = std_Object_create(null);
@@ -1978,46 +1933,67 @@ function InitializeNumberFormat(numberFormat, locales, options) {
opt.localeMatcher = matcher;
// Compute formatting options.
- // Step 14.
- var style = GetOption(options, "style", "string", ["decimal", "percent", "currency"], "decimal");
- lazyNumberFormatData.style = style;
+ // Step 15.
+ var s = GetOption(options, "style", "string", ["decimal", "percent", "currency"], "decimal");
+ lazyNumberFormatData.style = s;
- // Steps 16-19.
+ // Steps 17-20.
var c = GetOption(options, "currency", "string", undefined, undefined);
if (c !== undefined && !IsWellFormedCurrencyCode(c))
ThrowRangeError(JSMSG_INVALID_CURRENCY_CODE, c);
var cDigits;
- if (style === "currency") {
+ if (s === "currency") {
if (c === undefined)
ThrowTypeError(JSMSG_UNDEFINED_CURRENCY);
- // Steps 19.a-c.
+ // Steps 20.a-c.
c = toASCIIUpperCase(c);
lazyNumberFormatData.currency = c;
cDigits = CurrencyDigits(c);
}
- // Step 20.
+ // Step 21.
var cd = GetOption(options, "currencyDisplay", "string", ["code", "symbol", "name"], "symbol");
- if (style === "currency")
+ if (s === "currency")
lazyNumberFormatData.currencyDisplay = cd;
- // Steps 22-25.
- var mnfdDefault, mxfdDefault;
- if (style === "currency") {
- mnfdDefault = cDigits;
- mxfdDefault = cDigits;
- } else {
- mnfdDefault = 0;
- mxfdDefault = style === "percent" ? 0 : 3;
+ // Step 23.
+ var mnid = GetNumberOption(options, "minimumIntegerDigits", 1, 21, 1);
+ lazyNumberFormatData.minimumIntegerDigits = mnid;
+
+ // Steps 25-26.
+ var mnfdDefault = (s === "currency") ? cDigits : 0;
+ var mnfd = GetNumberOption(options, "minimumFractionDigits", 0, 20, mnfdDefault);
+ lazyNumberFormatData.minimumFractionDigits = mnfd;
+
+ // Steps 28-29.
+ var mxfdDefault;
+ if (s === "currency")
+ mxfdDefault = std_Math_max(mnfd, cDigits);
+ else if (s === "percent")
+ mxfdDefault = std_Math_max(mnfd, 0);
+ else
+ mxfdDefault = std_Math_max(mnfd, 3);
+ var mxfd = GetNumberOption(options, "maximumFractionDigits", mnfd, 20, mxfdDefault);
+ lazyNumberFormatData.maximumFractionDigits = mxfd;
+
+ // Steps 31-32.
+ var mnsd = options.minimumSignificantDigits;
+ var mxsd = options.maximumSignificantDigits;
+
+ // Step 33.
+ if (mnsd !== undefined || mxsd !== undefined) {
+ mnsd = GetNumberOption(options, "minimumSignificantDigits", 1, 21, 1);
+ mxsd = GetNumberOption(options, "maximumSignificantDigits", mnsd, 21, 21);
+ lazyNumberFormatData.minimumSignificantDigits = mnsd;
+ lazyNumberFormatData.maximumSignificantDigits = mxsd;
}
- SetNumberFormatDigitOptions(lazyNumberFormatData, options, mnfdDefault, mxfdDefault);
- // Steps 26.
+ // Step 34.
var g = GetOption(options, "useGrouping", "boolean", undefined, true);
lazyNumberFormatData.useGrouping = g;
- // Steps 35-36.
+ // Step 43.
//
// We've done everything that must be done now: mark the lazy data as fully
// computed and install it.
@@ -2026,6 +2002,43 @@ function InitializeNumberFormat(numberFormat, locales, options) {
/**
+ * Mapping from currency codes to the number of decimal digits used for them.
+ * Default is 2 digits.
+ *
+ * Spec: ISO 4217 Currency and Funds Code List.
+ * http://www.currency-iso.org/en/home/tables/table-a1.html
+ */
+var currencyDigits = {
+ BHD: 3,
+ BIF: 0,
+ BYR: 0,
+ CLF: 4,
+ CLP: 0,
+ DJF: 0,
+ GNF: 0,
+ IQD: 3,
+ ISK: 0,
+ JOD: 3,
+ JPY: 0,
+ KMF: 0,
+ KRW: 0,
+ KWD: 3,
+ LYD: 3,
+ OMR: 3,
+ PYG: 0,
+ RWF: 0,
+ TND: 3,
+ UGX: 0,
+ UYI: 0,
+ VND: 0,
+ VUV: 0,
+ XAF: 0,
+ XOF: 0,
+ XPF: 0
+};
+
+
+/**
* Returns the number of decimal digits to be used for the given currency.
*
* Spec: ECMAScript Internationalization API Specification, 11.1.1.
@@ -2106,7 +2119,7 @@ function numberFormatFormatToBind(value) {
// Step 1.a.ii-iii.
var x = ToNumber(value);
- return intl_FormatNumber(this, x, /* formatToParts = */ false);
+ return intl_FormatNumber(this, x);
}
@@ -2133,22 +2146,6 @@ function Intl_NumberFormat_format_get() {
// Step 2.
return internals.boundFormat;
}
-_SetCanonicalName(Intl_NumberFormat_format_get, "get format");
-
-
-function Intl_NumberFormat_formatToParts(value) {
- // Step 1.
- var nf = this;
-
- // Steps 2-3.
- getNumberFormatInternals(nf, "formatToParts");
-
- // Step 4.
- var x = ToNumber(value);
-
- // Step 5.
- return intl_FormatNumber(nf, x, /* formatToParts = */ true);
-}
/**
@@ -2290,6 +2287,26 @@ function getDateTimeFormatInternals(obj, methodName) {
return internalProps;
}
+/**
+ * Components of date and time formats and their values.
+ *
+ * Spec: ECMAScript Internationalization API Specification, 12.1.1.
+ */
+var dateTimeComponentValues = {
+ weekday: ["narrow", "short", "long"],
+ era: ["narrow", "short", "long"],
+ year: ["2-digit", "numeric"],
+ month: ["2-digit", "numeric", "narrow", "short", "long"],
+ day: ["2-digit", "numeric"],
+ hour: ["2-digit", "numeric"],
+ minute: ["2-digit", "numeric"],
+ second: ["2-digit", "numeric"],
+ timeZoneName: ["short", "long"]
+};
+
+
+var dateTimeComponents = std_Object_getOwnPropertyNames(dateTimeComponentValues);
+
/**
* Initializes an object as a DateTimeFormat.
@@ -2379,19 +2396,12 @@ function InitializeDateTimeFormat(dateTimeFormat, locales, options) {
lazyDateTimeFormatData.formatOpt = formatOpt;
// Step 19.
- // 12.1, Table 4: Components of date and time formats.
- formatOpt.weekday = GetOption(options, "weekday", "string", ["narrow", "short", "long"],
- undefined);
- formatOpt.era = GetOption(options, "era", "string", ["narrow", "short", "long"], undefined);
- formatOpt.year = GetOption(options, "year", "string", ["2-digit", "numeric"], undefined);
- formatOpt.month = GetOption(options, "month", "string",
- ["2-digit", "numeric", "narrow", "short", "long"], undefined);
- formatOpt.day = GetOption(options, "day", "string", ["2-digit", "numeric"], undefined);
- formatOpt.hour = GetOption(options, "hour", "string", ["2-digit", "numeric"], undefined);
- formatOpt.minute = GetOption(options, "minute", "string", ["2-digit", "numeric"], undefined);
- formatOpt.second = GetOption(options, "second", "string", ["2-digit", "numeric"], undefined);
- formatOpt.timeZoneName = GetOption(options, "timeZoneName", "string", ["short", "long"],
- undefined);
+ var i, prop;
+ for (i = 0; i < dateTimeComponents.length; i++) {
+ prop = dateTimeComponents[i];
+ var value = GetOption(options, prop, "string", dateTimeComponentValues[prop], undefined);
+ formatOpt[prop] = value;
+ }
// Steps 20-21 provided by ICU - see comment after this function.
@@ -2659,6 +2669,7 @@ function ToDateTimeOptions(options, required, defaults) {
return options;
}
+
/**
* Compares the date and time components requested by options with the available
* date and time formats in formats, and selects the best match according
@@ -2844,7 +2855,6 @@ function Intl_DateTimeFormat_format_get() {
// Step 2.
return internals.boundFormat;
}
-_SetCanonicalName(Intl_DateTimeFormat_format_get, "get format");
function Intl_DateTimeFormat_formatToParts() {
@@ -2980,232 +2990,6 @@ function resolveICUPattern(pattern, result) {
}
}
-/********** Intl.PluralRules **********/
-
-/**
- * PluralRules internal properties.
- *
- * Spec: ECMAScript 402 API, PluralRules, 1.3.3.
- */
-var pluralRulesInternalProperties = {
- _availableLocales: null,
- availableLocales: function()
- {
- var locales = this._availableLocales;
- if (locales)
- return locales;
-
- locales = intl_PluralRules_availableLocales();
- addSpecialMissingLanguageTags(locales);
- return (this._availableLocales = locales);
- }
-};
-
-/**
- * Compute an internal properties object from |lazyPluralRulesData|.
- */
-function resolvePluralRulesInternals(lazyPluralRulesData) {
- assert(IsObject(lazyPluralRulesData), "lazy data not an object?");
-
- var internalProps = std_Object_create(null);
-
- var requestedLocales = lazyPluralRulesData.requestedLocales;
-
- var PluralRules = pluralRulesInternalProperties;
-
- // Step 13.
- const r = ResolveLocale(callFunction(PluralRules.availableLocales, PluralRules),
- lazyPluralRulesData.requestedLocales,
- lazyPluralRulesData.opt,
- noRelevantExtensionKeys, undefined);
-
- // Step 14.
- internalProps.locale = r.locale;
- internalProps.type = lazyPluralRulesData.type;
-
- internalProps.pluralCategories = intl_GetPluralCategories(
- internalProps.locale,
- internalProps.type);
-
- internalProps.minimumIntegerDigits = lazyPluralRulesData.minimumIntegerDigits;
- internalProps.minimumFractionDigits = lazyPluralRulesData.minimumFractionDigits;
- internalProps.maximumFractionDigits = lazyPluralRulesData.maximumFractionDigits;
-
- if ("minimumSignificantDigits" in lazyPluralRulesData) {
- assert("maximumSignificantDigits" in lazyPluralRulesData, "min/max sig digits mismatch");
- internalProps.minimumSignificantDigits = lazyPluralRulesData.minimumSignificantDigits;
- internalProps.maximumSignificantDigits = lazyPluralRulesData.maximumSignificantDigits;
- }
-
- return internalProps;
-}
-
-/**
- * Returns an object containing the PluralRules internal properties of |obj|,
- * or throws a TypeError if |obj| isn't PluralRules-initialized.
- */
-function getPluralRulesInternals(obj, methodName) {
- var internals = getIntlObjectInternals(obj, "PluralRules", methodName);
- assert(internals.type === "PluralRules", "bad type escaped getIntlObjectInternals");
-
- var internalProps = maybeInternalProperties(internals);
- if (internalProps)
- return internalProps;
-
- internalProps = resolvePluralRulesInternals(internals.lazyData);
- setInternalProperties(internals, internalProps);
- return internalProps;
-}
-
-/**
- * Initializes an object as a PluralRules.
- *
- * This method is complicated a moderate bit by its implementing initialization
- * as a *lazy* concept. Everything that must happen now, does -- but we defer
- * all the work we can until the object is actually used as a PluralRules.
- * This later work occurs in |resolvePluralRulesInternals|; steps not noted
- * here occur there.
- *
- * Spec: ECMAScript 402 API, PluralRules, 1.1.1.
- */
-function InitializePluralRules(pluralRules, locales, options) {
- assert(IsObject(pluralRules), "InitializePluralRules");
-
- // Step 1.
- if (isInitializedIntlObject(pluralRules))
- ThrowTypeError(JSMSG_INTL_OBJECT_REINITED);
-
- let internals = initializeIntlObject(pluralRules);
-
- // Lazy PluralRules data has the following structure:
- //
- // {
- // requestedLocales: List of locales,
- // type: "cardinal" / "ordinal",
- //
- // opt: // opt object computer in InitializePluralRules
- // {
- // localeMatcher: "lookup" / "best fit",
- // }
- //
- // minimumIntegerDigits: integer ∈ [1, 21],
- // minimumFractionDigits: integer ∈ [0, 20],
- // maximumFractionDigits: integer ∈ [0, 20],
- //
- // // optional
- // minimumSignificantDigits: integer ∈ [1, 21],
- // maximumSignificantDigits: integer ∈ [1, 21],
- // }
- //
- // Note that lazy data is only installed as a final step of initialization,
- // so every PluralRules lazy data object has *all* these properties, never a
- // subset of them.
- const lazyPluralRulesData = std_Object_create(null);
-
- // Step 3.
- let requestedLocales = CanonicalizeLocaleList(locales);
- lazyPluralRulesData.requestedLocales = requestedLocales;
-
- // Steps 4-5.
- if (options === undefined)
- options = {};
- else
- options = ToObject(options);
-
- // Step 6.
- const type = GetOption(options, "type", "string", ["cardinal", "ordinal"], "cardinal");
- lazyPluralRulesData.type = type;
-
- // Step 8.
- let opt = new Record();
- lazyPluralRulesData.opt = opt;
-
- // Steps 9-10.
- let matcher = GetOption(options, "localeMatcher", "string", ["lookup", "best fit"], "best fit");
- opt.localeMatcher = matcher;
-
- // Steps 11-12.
- SetNumberFormatDigitOptions(lazyPluralRulesData, options, 0, 3);
-
- setLazyData(internals, "PluralRules", lazyPluralRulesData)
-}
-
-/**
- * Returns the subset of the given locale list for which this locale list has a
- * matching (possibly fallback) locale. Locales appear in the same order in the
- * returned list as in the input list.
- *
- * Spec: ECMAScript 402 API, PluralRules, 1.3.2.
- */
-function Intl_PluralRules_supportedLocalesOf(locales /*, options*/) {
- var options = arguments.length > 1 ? arguments[1] : undefined;
-
- // Step 1.
- var availableLocales = callFunction(pluralRulesInternalProperties.availableLocales,
- pluralRulesInternalProperties);
- // Step 2.
- let requestedLocales = CanonicalizeLocaleList(locales);
-
- // Step 3.
- return SupportedLocales(availableLocales, requestedLocales, options);
-}
-
-/**
- * Returns a String value representing the plural category matching
- * the number passed as value according to the
- * effective locale and the formatting options of this PluralRules.
- *
- * Spec: ECMAScript 402 API, PluralRules, 1.4.3.
- */
-function Intl_PluralRules_select(value) {
- // Step 1.
- let pluralRules = this;
- // Step 2.
- let internals = getPluralRulesInternals(pluralRules, "select");
-
- // Steps 3-4.
- let n = ToNumber(value);
-
- // Step 5.
- return intl_SelectPluralRule(pluralRules, n);
-}
-
-/**
- * Returns the resolved options for a PluralRules object.
- *
- * Spec: ECMAScript 402 API, PluralRules, 1.4.4.
- */
-function Intl_PluralRules_resolvedOptions() {
- var internals = getPluralRulesInternals(this, "resolvedOptions");
-
- var internalsPluralCategories = internals.pluralCategories;
- var pluralCategories = [];
- for (var i = 0; i < internalsPluralCategories.length; i++)
- _DefineDataProperty(pluralCategories, i, internalsPluralCategories[i]);
-
- var result = {
- locale: internals.locale,
- type: internals.type,
- pluralCategories,
- minimumIntegerDigits: internals.minimumIntegerDigits,
- minimumFractionDigits: internals.minimumFractionDigits,
- maximumFractionDigits: internals.maximumFractionDigits,
- };
-
- var optionalProperties = [
- "minimumSignificantDigits",
- "maximumSignificantDigits"
- ];
-
- for (var i = 0; i < optionalProperties.length; i++) {
- var p = optionalProperties[i];
- if (callFunction(std_Object_hasOwnProperty, internals, p))
- _DefineDataProperty(result, p, internals[p]);
- }
- return result;
-}
-
-
function Intl_getCanonicalLocales(locales) {
let codes = CanonicalizeLocaleList(locales);
let result = [];
@@ -3362,5 +3146,5 @@ function Intl_getDisplayNames(locales, options) {
// 24. Return result.
return result;
-}
+}
diff --git a/js/src/builtin/IntlTimeZoneData.h b/js/src/builtin/IntlTimeZoneData.h
index f92c583df..fa808c0b9 100644
--- a/js/src/builtin/IntlTimeZoneData.h
+++ b/js/src/builtin/IntlTimeZoneData.h
@@ -1,5 +1,5 @@
// Generated by make_intl_data.py. DO NOT EDIT.
-// tzdata version = 2018c
+// tzdata version = 2018e
#ifndef builtin_IntlTimeZoneData_h
#define builtin_IntlTimeZoneData_h
diff --git a/js/src/builtin/Map.js b/js/src/builtin/Map.js
index 580629a13..434cd6529 100644
--- a/js/src/builtin/Map.js
+++ b/js/src/builtin/Map.js
@@ -62,8 +62,8 @@ function MapIteratorNext() {
var O = this;
// Steps 2-3.
- if (!IsObject(O) || !IsMapIterator(O))
- return callFunction(CallMapIteratorMethodIfWrapped, O, "MapIteratorNext");
+ if (!IsObject(O) || (O = GuardToMapIterator(O)) === null)
+ return callFunction(CallMapIteratorMethodIfWrapped, this, "MapIteratorNext");
// Steps 4-5 (implemented in _GetNextMapEntryForIterator).
// Steps 8-9 (omitted).
@@ -82,7 +82,7 @@ function MapIteratorNext() {
// Steps 10.b-c (omitted).
// Step 6.
- var itemKind = UnsafeGetInt32FromReservedSlot(this, ITERATOR_SLOT_ITEM_KIND);
+ var itemKind = UnsafeGetInt32FromReservedSlot(O, ITERATOR_SLOT_ITEM_KIND);
var result;
if (itemKind === ITEM_KIND_KEY) {
diff --git a/js/src/builtin/Set.js b/js/src/builtin/Set.js
index 9af6cf8d1..e2571e66a 100644
--- a/js/src/builtin/Set.js
+++ b/js/src/builtin/Set.js
@@ -64,8 +64,8 @@ function SetIteratorNext() {
var O = this;
// Steps 2-3.
- if (!IsObject(O) || !IsSetIterator(O))
- return callFunction(CallSetIteratorMethodIfWrapped, O, "SetIteratorNext");
+ if (!IsObject(O) || (O = GuardToSetIterator(O)) === null)
+ return callFunction(CallSetIteratorMethodIfWrapped, this, "SetIteratorNext");
// Steps 4-5 (implemented in _GetNextSetEntryForIterator).
// Steps 8-9 (omitted).
@@ -83,7 +83,7 @@ function SetIteratorNext() {
// Steps 10.b-c (omitted).
// Step 6.
- var itemKind = UnsafeGetInt32FromReservedSlot(this, ITERATOR_SLOT_ITEM_KIND);
+ var itemKind = UnsafeGetInt32FromReservedSlot(O, ITERATOR_SLOT_ITEM_KIND);
var result;
if (itemKind === ITEM_KIND_VALUE) {
diff --git a/js/src/builtin/String.js b/js/src/builtin/String.js
index 4202d0de6..e5b2ad552 100644
--- a/js/src/builtin/String.js
+++ b/js/src/builtin/String.js
@@ -529,16 +529,17 @@ function String_iterator() {
}
function StringIteratorNext() {
- if (!IsObject(this) || !IsStringIterator(this)) {
+ var obj;
+ if (!IsObject(this) || (obj = GuardToStringIterator(this)) === null) {
return callFunction(CallStringIteratorMethodIfWrapped, this,
"StringIteratorNext");
}
- var S = UnsafeGetStringFromReservedSlot(this, ITERATOR_SLOT_TARGET);
+ var S = UnsafeGetStringFromReservedSlot(obj, ITERATOR_SLOT_TARGET);
// We know that JSString::MAX_LENGTH <= INT32_MAX (and assert this in
// SelfHostring.cpp) so our current index can never be anything other than
// an Int32Value.
- var index = UnsafeGetInt32FromReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX);
+ var index = UnsafeGetInt32FromReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX);
var size = S.length;
var result = { value: undefined, done: false };
@@ -556,7 +557,7 @@ function StringIteratorNext() {
}
}
- UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + charCount);
+ UnsafeSetReservedSlot(obj, ITERATOR_SLOT_NEXT_INDEX, index + charCount);
result.value = callFunction(String_substring, S, index, index + charCount);
return result;
@@ -659,11 +660,7 @@ function String_static_localeCompare(str1, str2) {
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "String.localeCompare");
var locales = arguments.length > 2 ? arguments[2] : undefined;
var options = arguments.length > 3 ? arguments[3] : undefined;
-#if EXPOSE_INTL_API
return callFunction(String_localeCompare, str1, str2, locales, options);
-#else
- return callFunction(std_String_localeCompare, str1, str2, locales, options);
-#endif
}
// ES6 draft 2014-04-27 B.2.3.3
@@ -855,14 +852,12 @@ function String_static_toLocaleUpperCase(string) {
return callFunction(std_String_toLocaleUpperCase, string);
}
-#if EXPOSE_INTL_API
function String_static_normalize(string) {
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.normalize');
var form = arguments.length > 1 ? arguments[1] : undefined;
return callFunction(std_String_normalize, string, form);
}
-#endif
function String_static_concat(string, arg1) {
if (arguments.length < 1)
diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp
index a14f9ba69..373b6c9ed 100644
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -236,11 +236,7 @@ GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp)
if (!JS_SetProperty(cx, info, "binary-data", value))
return false;
-#ifdef EXPOSE_INTL_API
value = BooleanValue(true);
-#else
- value = BooleanValue(false);
-#endif
if (!JS_SetProperty(cx, info, "intl-api", value))
return false;
@@ -2092,7 +2088,7 @@ class CloneBufferObject : public NativeObject {
Rooted<CloneBufferObject*> obj(cx, Create(cx));
if (!obj)
return nullptr;
- auto data = js::MakeUnique<JSStructuredCloneData>();
+ auto data = js::MakeUnique<JSStructuredCloneData>(buffer->scope());
if (!data) {
ReportOutOfMemory(cx);
return nullptr;
@@ -2145,8 +2141,11 @@ class CloneBufferObject : public NativeObject {
return false;
size_t nbytes = JS_GetStringLength(args[0].toString());
MOZ_ASSERT(nbytes % sizeof(uint64_t) == 0);
- auto buf = js::MakeUnique<JSStructuredCloneData>(nbytes, nbytes, nbytes);
- js_memcpy(buf->Start(), str, nbytes);
+ auto buf = js::MakeUnique<JSStructuredCloneData>(JS::StructuredCloneScope::DifferentProcess);
+ if (!buf->AppendBytes(str, nbytes)) {
+ ReportOutOfMemory(cx);
+ return false;
+ }
JS_free(cx, str);
obj->setData(buf.release());
@@ -2190,7 +2189,7 @@ class CloneBufferObject : public NativeObject {
ReportOutOfMemory(cx);
return false;
}
- auto iter = obj->data()->Iter();
+ auto iter = obj->data()->Start();
obj->data()->ReadBytes(iter, buffer.get(), size);
JSString* str = JS_NewStringCopyN(cx, buffer.get(), size);
if (!str)
@@ -2248,6 +2247,8 @@ ParseCloneScope(JSContext* cx, HandleString str)
scope.emplace(JS::StructuredCloneScope::SameProcessDifferentThread);
else if (strcmp(scopeStr.ptr(), "DifferentProcess") == 0)
scope.emplace(JS::StructuredCloneScope::DifferentProcess);
+ else if (strcmp(scopeStr.ptr(), "DifferentProcessForIndexedDB") == 0)
+ scope.emplace(JS::StructuredCloneScope::DifferentProcessForIndexedDB);
return scope;
}
@@ -4374,19 +4375,22 @@ JS_FN_HELP("rejectPromise", RejectPromise, 2, 0,
" clone buffer object. 'policy' may be an options hash. Valid keys:\n"
" 'SharedArrayBuffer' - either 'allow' (the default) or 'deny'\n"
" to specify whether SharedArrayBuffers may be serialized.\n"
-"\n"
-" 'scope' - SameProcessSameThread, SameProcessDifferentThread, or\n"
-" DifferentProcess. Determines how some values will be serialized.\n"
-" Clone buffers may only be deserialized with a compatible scope."),
+" 'scope' - SameProcessSameThread, SameProcessDifferentThread,\n"
+" DifferentProcess, or DifferentProcessForIndexedDB. Determines how some\n"
+" values will be serialized. Clone buffers may only be deserialized with a\n"
+" compatible scope. NOTE - For DifferentProcess/DifferentProcessForIndexedDB,\n"
+" must also set SharedArrayBuffer:'deny' if data contains any shared memory\n"
+" object."),
JS_FN_HELP("deserialize", Deserialize, 1, 0,
"deserialize(clonebuffer[, opts])",
" Deserialize data generated by serialize. 'opts' is an options hash with one\n"
" recognized key 'scope', which limits the clone buffers that are considered\n"
" valid. Allowed values: 'SameProcessSameThread', 'SameProcessDifferentThread',\n"
-" and 'DifferentProcess'. So for example, a DifferentProcess clone buffer\n"
-" may be deserialized in any scope, but a SameProcessSameThread clone buffer\n"
-" cannot be deserialized in a DifferentProcess scope."),
+" 'DifferentProcess', and 'DifferentProcessForIndexedDB'. So for example, a\n"
+" DifferentProcessForIndexedDB clone buffer may be deserialized in any scope, but\n"
+" a SameProcessSameThread clone buffer cannot be deserialized in a\n"
+" DifferentProcess scope."),
JS_FN_HELP("detachArrayBuffer", DetachArrayBuffer, 1, 0,
"detachArrayBuffer(buffer)",
diff --git a/js/src/builtin/TypedArray.js b/js/src/builtin/TypedArray.js
index a2205dc92..a1934051d 100644
--- a/js/src/builtin/TypedArray.js
+++ b/js/src/builtin/TypedArray.js
@@ -1232,11 +1232,7 @@ function TypedArrayToLocaleString(locales = undefined, options = undefined) {
// Steps 6-7.
// Omit the 'if' clause in step 6, since typed arrays can't have undefined
// or null elements.
-#if EXPOSE_INTL_API
var R = ToString(callContentFunction(firstElement.toLocaleString, firstElement, locales, options));
-#else
- var R = ToString(callContentFunction(firstElement.toLocaleString, firstElement));
-#endif
// Step 3 (reordered).
// We don't (yet?) implement locale-dependent separators.
@@ -1258,11 +1254,7 @@ function TypedArrayToLocaleString(locales = undefined, options = undefined) {
// the error message. So despite bug 1079853, we can skip step 9.c.
// Step 9.d.
-#if EXPOSE_INTL_API
R = ToString(callContentFunction(nextElement.toLocaleString, nextElement, locales, options));
-#else
- R = ToString(callContentFunction(nextElement.toLocaleString, nextElement));
-#endif
// Step 9.e.
R = S + R;