--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -731,17 +731,17 @@ struct JSClass {
// with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
// previously allowed, but is now an ES5 violation and thus unsupported.
//
// JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at
// the beginning of every global object's slots for use by the
// application.
#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
#define JSCLASS_GLOBAL_SLOT_COUNT \
- (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 39)
+ (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 40)
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
#define JSCLASS_GLOBAL_FLAGS \
JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
#define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp) \
(((clasp)->flags & JSCLASS_IS_GLOBAL) \
&& JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -24,16 +24,17 @@
#include "builtin/IntlTimeZoneData.h"
#if ENABLE_INTL_API
#include "unicode/ucal.h"
#include "unicode/ucol.h"
#include "unicode/udat.h"
#include "unicode/udatpg.h"
#include "unicode/uenum.h"
+#include "unicode/ulistformatter.h"
#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"
#include "vm/Stack.h"
@@ -2826,16 +2827,265 @@ js::intl_FormatDateTime(JSContext* cx, u
if (!isDateTimeFormatInstance)
udat_close(df);
if (!success)
return false;
args.rval().set(result);
return true;
}
+/**************** ListFormat *****************/
+
+static void listFormat_finalize(FreeOp* fop, JSObject* obj);
+
+static const uint32_t ULIST_FORMAT_SLOT = 0;
+static const uint32_t LIST_FORMAT_SLOTS_COUNT = 1;
+
+static const ClassOps ListFormatClassOps = {
+ nullptr, /* addProperty */
+ nullptr, /* delProperty */
+ nullptr, /* getProperty */
+ nullptr, /* setProperty */
+ nullptr, /* enumerate */
+ nullptr, /* resolve */
+ nullptr, /* mayResolve */
+ listFormat_finalize
+};
+
+static const Class ListFormatClass = {
+ js_Object_str,
+ JSCLASS_HAS_RESERVED_SLOTS(LIST_FORMAT_SLOTS_COUNT) |
+ JSCLASS_FOREGROUND_FINALIZE,
+ &ListFormatClassOps
+};
+
+#if JS_HAS_TOSOURCE
+static bool
+listFormat_toSource(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ args.rval().setString(cx->names().ListFormat);
+ return true;
+}
+#endif
+
+static const JSFunctionSpec listFormat_static_methods[] = {
+ JS_SELF_HOSTED_FN("supportedLocalesOf", "Intl_ListFormat_supportedLocalesOf", 1, 0),
+ JS_FS_END
+};
+
+static const JSFunctionSpec listFormat_methods[] = {
+ JS_SELF_HOSTED_FN("resolvedOptions", "Intl_ListFormat_resolvedOptions", 0, 0),
+ JS_SELF_HOSTED_FN("format", "Intl_ListFormat_format", 1, 0),
+#if JS_HAS_TOSOURCE
+ JS_FN(js_toSource_str, listFormat_toSource, 0, 0),
+#endif
+ JS_FS_END
+};
+
+static bool
+ListFormat(JSContext* cx, const CallArgs& args, bool construct)
+{
+ RootedObject obj(cx);
+
+ if (!construct) {
+ JSObject* intl = cx->global()->getOrCreateIntlObject(cx);
+ if (!intl)
+ return false;
+ RootedValue self(cx, args.thisv());
+ if (!self.isUndefined() && (!self.isObject() || self.toObject() != *intl)) {
+ obj = ToObject(cx, self);
+ if (!obj)
+ return false;
+
+ bool extensible;
+ if (!IsExtensible(cx, obj, &extensible))
+ return false;
+ if (!extensible)
+ return Throw(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE);
+ } else {
+ construct = true;
+ }
+ }
+ if (construct) {
+ RootedObject proto(cx, cx->global()->getOrCreateListFormatPrototype(cx));
+ if (!proto)
+ return false;
+ obj = NewObjectWithGivenProto(cx, &ListFormatClass, proto);
+ if (!obj)
+ return false;
+
+ obj->as<NativeObject>().setReservedSlot(ULIST_FORMAT_SLOT, PrivateValue(nullptr));
+ }
+
+ RootedValue locales(cx, args.get(0));
+ RootedValue options(cx, args.get(1));
+
+ if (!IntlInitialize(cx, obj, cx->names().InitializeListFormat, locales, options))
+ return false;
+
+ args.rval().setObject(*obj);
+ return true;
+}
+
+static bool
+ListFormat(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ return ListFormat(cx, args, args.isConstructing());
+}
+
+bool
+js::intl_ListFormat(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ MOZ_ASSERT(args.length() == 2);
+ return ListFormat(cx, args, true);
+}
+
+static void
+listFormat_finalize(FreeOp* fop, JSObject* obj)
+{
+ MOZ_ASSERT(fop->onMainThread());
+
+ // This is-undefined check shouldn't be necessary, but for internal
+ // brokenness in object allocation code. For the moment, hack around it by
+ // explicitly guarding against the possibility of the reserved slot not
+ // containing a private. See bug 949220.
+ const Value& slot = obj->as<NativeObject>().getReservedSlot(ULIST_FORMAT_SLOT);
+ if (!slot.isUndefined()) {
+ if (UListFormatter* lf = static_cast<UListFormatter*>(slot.toPrivate()))
+ ulistfmt_close(lf);
+ }
+}
+
+static JSObject*
+CreateListFormatPrototype(JSContext* cx, HandleObject Intl, Handle<GlobalObject*> global)
+{
+ RootedFunction ctor(cx);
+ ctor = global->createConstructor(cx, &ListFormat, cx->names().ListFormat, 0);
+ if (!ctor)
+ return nullptr;
+
+ RootedNativeObject proto(cx, global->createBlankPrototype(cx, &ListFormatClass));
+ if (!proto)
+ return nullptr;
+ proto->setReservedSlot(ULIST_FORMAT_SLOT, PrivateValue(nullptr));
+
+ if (!LinkConstructorAndPrototype(cx, ctor, proto))
+ return nullptr;
+
+ if (!JS_DefineFunctions(cx, ctor, listFormat_static_methods))
+ return nullptr;
+
+ if (!JS_DefineFunctions(cx, proto, listFormat_methods))
+ return nullptr;
+
+ RootedValue options(cx);
+ if (!CreateDefaultOptions(cx, &options))
+ return nullptr;
+
+ if (!IntlInitialize(cx, proto, cx->names().InitializeListFormat, UndefinedHandleValue,
+ options))
+ {
+ return nullptr;
+ }
+
+ RootedValue ctorValue(cx, ObjectValue(*ctor));
+ if (!DefineProperty(cx, Intl, cx->names().ListFormat, ctorValue, nullptr, nullptr, 0))
+ return nullptr;
+
+ return proto;
+}
+
+bool
+js::intl_ListFormat_availableLocales(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+ MOZ_ASSERT(args.length() == 0);
+
+ RootedValue result(cx);
+ // We're going to use ULocale availableLocales as per ICU recommendation:
+ // [http://bugs.icu-project.org/trac/ticket/12756].
+ if (!intl_availableLocales(cx, uloc_countAvailable, uloc_getAvailable, &result))
+ return false;
+ args.rval().set(result);
+ return true;
+}
+
+bool
+js::intl_FormatListFormat(JSContext* cx, unsigned argc, Value* vp)
+{
+ CallArgs args = CallArgsFromVp(argc, vp);
+
+ RootedObject listFormat(cx, &args[0].toObject());
+ RootedArrayObject elements(cx, &args[1].toObject().as<ArrayObject>());
+ if (!elements)
+ return false;
+
+
+ RootedObject internals(cx, GetInternals(cx, listFormat));
+ if (!internals)
+ return false;
+
+ RootedValue value(cx);
+
+ if (!GetProperty(cx, internals, internals, cx->names().locale, &value))
+ return false;
+ JSAutoByteString locale(cx, value.toString());
+ if (!locale)
+ return false;
+
+ if (!GetProperty(cx, internals, internals, cx->names().type, &value))
+ return false;
+ JSAutoByteString type(cx, value.toString());
+ if (!type)
+ return false;
+
+ UErrorCode status = U_ZERO_ERROR;
+
+ UListFormatter* lf = ulistfmt_open(icuLocale(locale.ptr()), &status);
+
+ ScopedICUObject<UListFormatter, ulistfmt_close> closeListFormat(lf);
+
+ int32_t stringCount = elements->length();
+ const UChar* strings[stringCount];
+ int32_t stringLengths[stringCount];
+
+ RootedValue elemValue(cx);
+ RootedString elemValStr(cx);
+
+ for (int32_t i = 0; i < stringCount; i++) {
+ if (!GetElement(cx, elements, elements, i, &elemValue))
+ return false;
+
+ AutoStableStringChars stableChars(cx);
+ stableChars.initTwoByte(cx, elemValue.toString());
+ mozilla::Range<const char16_t> pchars = stableChars.twoByteRange();
+
+ strings[i] = Char16ToUChar(pchars.begin().get());
+ stringLengths[i] = pchars.length();
+ printf("%d - %d\n", i, int(pchars.length()));
+ }
+
+ Vector<char16_t, INITIAL_CHAR_BUFFER_SIZE> chars(cx);
+ int32_t resCapacity = INITIAL_CHAR_BUFFER_SIZE;
+
+ int size = ulistfmt_format(lf, strings, stringLengths, stringCount,
+ Char16ToUChar(chars.begin()), resCapacity, &status);
+
+
+ JSString* word = NewStringCopyN<CanGC>(cx,
+ chars.begin(), size);
+
+ args.rval().setString(word);
+ return true;
+}
+
+
bool
js::intl_GetCalendarInfo(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
JSAutoByteString locale(cx, args[0].toString());
if (!locale)
@@ -2974,16 +3224,19 @@ GlobalObject::initIntlObject(JSContext*
if (!collatorProto)
return false;
RootedObject dateTimeFormatProto(cx, CreateDateTimeFormatPrototype(cx, intl, global));
if (!dateTimeFormatProto)
return false;
RootedObject numberFormatProto(cx, CreateNumberFormatPrototype(cx, intl, global));
if (!numberFormatProto)
return false;
+ RootedObject listFormatProto(cx, CreateListFormatPrototype(cx, intl, global));
+ if (!listFormatProto)
+ return false;
// The |Intl| object is fully set up now, so define the global property.
RootedValue intlValue(cx, ObjectValue(*intl));
if (!DefineProperty(cx, global, cx->names().Intl, intlValue, nullptr, nullptr,
JSPROP_RESOLVING))
{
return false;
}
@@ -2995,16 +3248,17 @@ GlobalObject::initIntlObject(JSContext*
// objects with the proper [[Prototype]] as "the original value of
// |Intl.Collator.prototype|" and similar. For builtin classes like
// |String.prototype| we have |JSProto_*| that enables
// |getPrototype(JSProto_*)|, but that has global-object-property-related
// baggage we don't need or want, so we use one-off reserved slots.
global->setReservedSlot(COLLATOR_PROTO, ObjectValue(*collatorProto));
global->setReservedSlot(DATE_TIME_FORMAT_PROTO, ObjectValue(*dateTimeFormatProto));
global->setReservedSlot(NUMBER_FORMAT_PROTO, ObjectValue(*numberFormatProto));
+ global->setReservedSlot(LIST_FORMAT_PROTO, ObjectValue(*listFormatProto));
// Also cache |Intl| to implement spec language that conditions behavior
// based on values being equal to "the standard built-in |Intl| object".
// Use |setConstructor| to correspond with |JSProto_Intl|.
//
// XXX We should possibly do a one-off reserved slot like above.
global->setConstructor(JSProto_Intl, ObjectValue(*intl));
return true;
--- a/js/src/builtin/Intl.h
+++ b/js/src/builtin/Intl.h
@@ -358,16 +358,39 @@ intl_patternForSkeleton(JSContext* cx, u
*
* Spec: ECMAScript Internationalization API Specification, 12.3.2.
*
* Usage: formatted = intl_FormatDateTime(dateTimeFormat, x)
*/
extern MOZ_MUST_USE bool
intl_FormatDateTime(JSContext* cx, unsigned argc, Value* vp);
+/******************** ListFormat ********************/
+
+/**
+ * Returns a new ListFormat instance.
+ * Self-hosted code cannot cache this constructor (as it does for others in
+ * Utilities.js) because it is initialized after self-hosted code is compiled.
+ *
+ * Usage: listFormat = intl_ListFormat(locales, options)
+ */
+extern MOZ_MUST_USE bool
+intl_ListFormat(JSContext* cx, unsigned argc, Value* vp);
+
+extern MOZ_MUST_USE bool
+intl_ListFormat_availableLocales(JSContext* cx, unsigned argc, Value* vp);
+
+extern MOZ_MUST_USE bool
+intl_FormatListFormat(JSContext* cx, unsigned argc, Value* vp);
+
+/*
+MOZ_MUST_USE JSObject*
+CreateListFormatPrototype(JSContext* cx, HandleObject Intl, Handle<GlobalObject*> global);
+*/
+
/**
* Returns a plain object with calendar information for a single valid locale
* (callers must perform this validation). The object will have these
* properties:
*
* firstDayOfWeek
* an integer in the range 1=Sunday to 7=Saturday indicating the day
* considered the first day of the week in calendars, e.g. 1 for en-US,
--- a/js/src/builtin/Intl.js
+++ b/js/src/builtin/Intl.js
@@ -1246,17 +1246,18 @@ function initializeIntlObject(obj) {
/**
* Mark |internals| as having the given type and lazy data.
*/
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", "bad type");
+ assert(type === "Collator" || type === "DateTimeFormat" ||
+ type == "NumberFormat" || type === "ListFormat", "bad type");
assert(IsObject(lazyData), "non-object lazy data");
// Set in reverse order so that the .type change is a barrier.
internals.lazyData = lazyData;
internals.type = type;
}
@@ -1296,17 +1297,18 @@ function maybeInternalProperties(interna
* Return whether |obj| has an[[initializedIntlObject]] property set to true.
*/
function isInitializedIntlObject(obj) {
#ifdef DEBUG
var internals = callFunction(std_WeakMap_get, internalsMap, 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", "unexpected type");
+ assert(type === "partial" || type === "Collator" ||
+ type === "DateTimeFormat" || type === "NumberFormat" || type === "ListFormat", "unexpected type");
assert(callFunction(std_Object_hasOwnProperty, internals, "lazyData"), "missing lazyData");
assert(callFunction(std_Object_hasOwnProperty, internals, "internalProps"), "missing internalProps");
} else {
assert(internals === undefined, "bad mapping for |obj|");
}
#endif
return callFunction(std_WeakMap_has, internalsMap, obj);
}
@@ -1353,16 +1355,18 @@ function getInternals(obj)
return internals.internalProps;
var internalProps;
var type = internals.type;
if (type === "Collator")
internalProps = resolveCollatorInternals(lazyData)
else if (type === "DateTimeFormat")
internalProps = resolveDateTimeFormatInternals(lazyData)
+ else if (type === "ListFormat")
+ internalProps = resolveListFormatInternals(lazyData)
else
internalProps = resolveNumberFormatInternals(lazyData);
setInternalProperties(internals, internalProps);
return internalProps;
}
/********** Intl.Collator **********/
@@ -2964,16 +2968,162 @@ function resolveICUPattern(pattern, resu
if (c === "h" || c === "K")
_DefineDataProperty(result, "hour12", true);
else if (c === "H" || c === "k")
_DefineDataProperty(result, "hour12", false);
}
}
}
+/********** Intl.ListFormat **********/
+
+var listFormatInternalProperties = {
+ _availableLocales: null,
+ availableLocales: function()
+ {
+ var locales = this._availableLocales;
+ if (locales)
+ return locales;
+
+ locales = intl_ListFormat_availableLocales();
+ addSpecialMissingLanguageTags(locales);
+ return (this._availableLocales = locales);
+ }
+};
+
+var noRelevantExtensionKeys = [];
+
+function resolveListFormatInternals(lazyListFormatData) {
+ assert(IsObject(lazyListFormatData), "lazy data not an object?");
+
+ var internalProps = std_Object_create(null);
+
+ var requestedLocales = lazyListFormatData.requestedLocales;
+
+ var ListFormat = listFormatInternalProperties;
+
+ // Step 13.
+ const r = ResolveLocale(callFunction(ListFormat.availableLocales, ListFormat),
+ lazyListFormatData.requestedLocales,
+ lazyListFormatData.opt,
+ noRelevantExtensionKeys, undefined);
+
+ // Step 14.
+ internalProps.locale = r.locale;
+ internalProps.type = lazyListFormatData.type;
+ internalProps.style = lazyListFormatData.style;
+
+ return internalProps;
+}
+
+function getListFormatInternals(obj, methodName) {
+ var internals = getIntlObjectInternals(obj, "ListFormat", methodName);
+ assert(internals.type === "ListFormat", "bad type escaped getIntlObjectInternals");
+
+ var internalProps = maybeInternalProperties(internals);
+ if (internalProps)
+ return internalProps;
+
+ internalProps = resolveListFormatInternals(internals.lazyData);
+ setInternalProperties(internals, internalProps);
+ return internalProps;
+}
+
+function InitializeListFormat(listFormat, locales, options) {
+ assert(IsObject(listFormat), "InitializeListFormat");
+
+ // Step 1.
+ if (isInitializedIntlObject(listFormat))
+ ThrowTypeError(JSMSG_INTL_OBJECT_REINITED);
+
+ let internals = initializeIntlObject(listFormat);
+
+ // Lazy ListFormat data has the following structure:
+ //
+ // {
+ // requestedLocales: List of locales,
+ // type: "standard" / "unit",
+ // style: "long" / "short" / "narrow",
+ //
+ // opt: // opt object computer in InitializeListFormat
+ // {
+ // localeMatcher: "lookup" / "best fit",
+ // }
+ // }
+ //
+ // Note that lazy data is only installed as a final step of initialization,
+ // so every ListFormat lazy data object has *all* these properties, never a
+ // subset of them.
+ const lazyListFormatData = std_Object_create(null);
+
+ // Step 3.
+ let requestedLocales = CanonicalizeLocaleList(locales);
+ lazyListFormatData.requestedLocales = requestedLocales;
+
+ // Steps 4-5.
+ if (options === undefined)
+ options = {};
+ else
+ options = ToObject(options);
+
+ // Step 6
+ const type = GetOption(options, "type", "string", ["standard", "unit"], "standard");
+
+ // Step 7.
+ lazyListFormatData.type = type;
+
+ // Step 8.
+ let opt = new Record();
+ lazyListFormatData.opt = opt;
+
+ // Steps 9-10.
+ let matcher = GetOption(options, "localeMatcher", "string", ["lookup", "best fit"], "best fit");
+ opt.localeMatcher = matcher;
+
+ setLazyData(internals, "ListFormat", lazyListFormatData)
+}
+
+function Intl_ListFormat_supportedLocalesOf(locales /*, options*/) {
+ var options = arguments.length > 1 ? arguments[1] : undefined;
+
+ // Step 1.
+ var availableLocales = callFunction(listFormatInternalProperties.availableLocales,
+ listFormatInternalProperties);
+ // Step 2.
+ let requestedLocales = CanonicalizeLocaleList(locales);
+
+ // Step 3.
+ return SupportedLocales(availableLocales, requestedLocales, options);
+}
+
+function Intl_ListFormat_format(value) {
+ // Step 1.
+ let listFormat = this;
+ // Step 2.
+ let internals = getListFormatInternals(listFormat, "format");
+
+ // Steps 3-4.
+ let n = value;
+
+ // Step 5.
+ return intl_FormatListFormat(listFormat, n);
+}
+
+function Intl_ListFormat_resolvedOptions() {
+ var internals = getListFormatInternals(this, "resolvedOptions");
+
+ var result = {
+ locale: internals.locale,
+ style: internals.style,
+ type: internals.type,
+ };
+
+ return result;
+}
+
function Intl_getCanonicalLocales(locales) {
let codes = CanonicalizeLocaleList(locales);
let result = [];
let len = codes.length;
let k = 0;
while (k < len) {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -59,16 +59,17 @@
#ifdef XP_WIN
# include "jswin.h"
#endif
#include "jswrapper.h"
#include "shellmoduleloader.out.h"
#include "builtin/ModuleObject.h"
#include "builtin/TestingFunctions.h"
+#include "builtin/Intl.h"
#include "frontend/Parser.h"
#include "gc/GCInternals.h"
#include "jit/arm/Simulator-arm.h"
#include "jit/InlinableNatives.h"
#include "jit/Ion.h"
#include "jit/JitcodeMap.h"
#include "jit/OptimizationTracking.h"
#include "js/Debug.h"
@@ -908,16 +909,31 @@ AddIntlExtras(JSContext* cx, unsigned ar
static const JSFunctionSpec funcs[] = {
JS_SELF_HOSTED_FN("getCalendarInfo", "Intl_getCalendarInfo", 1, 0),
JS_FS_END
};
if (!JS_DefineFunctions(cx, intl, funcs))
return false;
+ /*
+ Rooted<GlobalObject*> global(cx, cx->global());
+ if (!global)
+ return false;
+
+ RootedObject listFormatProto(cx, js::CreateListFormatPrototype(cx, intl, global));
+ if (!listFormatProto)
+ return false;
+
+ RootedValue elem(cx);
+ elem.setObject(*listFormatProto);
+ if (!DefineProperty(cx, intl, cx->names().ListFormat, elem))
+ return false;
+ */
+
args.rval().setUndefined();
return true;
}
#endif // ENABLE_INTL_API
static bool
EvalAndPrint(JSContext* cx, const char* bytes, size_t length,
int lineno, bool compileOnly)
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -147,16 +147,17 @@
macro(ignoreCase, ignoreCase, "ignoreCase") \
macro(ignorePunctuation, ignorePunctuation, "ignorePunctuation") \
macro(includes, includes, "includes") \
macro(incumbentGlobal, incumbentGlobal, "incumbentGlobal") \
macro(index, index, "index") \
macro(Infinity, Infinity, "Infinity") \
macro(InitializeCollator, InitializeCollator, "InitializeCollator") \
macro(InitializeDateTimeFormat, InitializeDateTimeFormat, "InitializeDateTimeFormat") \
+ macro(InitializeListFormat, InitializeListFormat, "InitializeListFormat") \
macro(InitializeNumberFormat, InitializeNumberFormat, "InitializeNumberFormat") \
macro(innermost, innermost, "innermost") \
macro(inNursery, inNursery, "inNursery") \
macro(input, input, "input") \
macro(int8, int8, "int8") \
macro(int16, int16, "int16") \
macro(int32, int32, "int32") \
macro(Int8x16, Int8x16, "Int8x16") \
@@ -176,16 +177,17 @@
macro(keys, keys, "keys") \
macro(label, label, "label") \
macro(lastIndex, lastIndex, "lastIndex") \
macro(LegacyGeneratorCloseInternal, LegacyGeneratorCloseInternal, "LegacyGeneratorCloseInternal") \
macro(length, length, "length") \
macro(let, let, "let") \
macro(line, line, "line") \
macro(lineNumber, lineNumber, "lineNumber") \
+ macro(ListFormat, ListFormat, "ListFormat") \
macro(literal, literal, "literal") \
macro(loc, loc, "loc") \
macro(locale, locale, "locale") \
macro(lookupGetter, lookupGetter, "__lookupGetter__") \
macro(lookupSetter, lookupSetter, "__lookupSetter__") \
macro(MapConstructorInit, MapConstructorInit, "MapConstructorInit") \
macro(MapIterator, MapIterator, "Map Iterator") \
macro(maximumFractionDigits, maximumFractionDigits, "maximumFractionDigits") \
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -99,16 +99,17 @@ class GlobalObject : public NativeObject
STAR_GENERATOR_FUNCTION,
ASYNC_FUNCTION_PROTO,
ASYNC_FUNCTION,
MAP_ITERATOR_PROTO,
SET_ITERATOR_PROTO,
COLLATOR_PROTO,
NUMBER_FORMAT_PROTO,
DATE_TIME_FORMAT_PROTO,
+ LIST_FORMAT_PROTO,
MODULE_PROTO,
IMPORT_ENTRY_PROTO,
EXPORT_ENTRY_PROTO,
REGEXP_STATICS,
WARNED_ONCE_FLAGS,
RUNTIME_CODEGEN_ENABLED,
DEBUGGERS,
INTRINSICS,
@@ -482,16 +483,20 @@ class GlobalObject : public NativeObject
JSObject* getOrCreateNumberFormatPrototype(JSContext* cx) {
return getOrCreateObject(cx, NUMBER_FORMAT_PROTO, initIntlObject);
}
JSObject* getOrCreateDateTimeFormatPrototype(JSContext* cx) {
return getOrCreateObject(cx, DATE_TIME_FORMAT_PROTO, initIntlObject);
}
+ JSObject* getOrCreateListFormatPrototype(JSContext* cx) {
+ return getOrCreateObject(cx, LIST_FORMAT_PROTO, initIntlObject);
+ }
+
static bool ensureModulePrototypesCreated(JSContext *cx, Handle<GlobalObject*> global);
JSObject* maybeGetModulePrototype() {
Value value = getSlot(MODULE_PROTO);
return value.isUndefined() ? nullptr : &value.toObject();
}
JSObject* maybeGetImportEntryPrototype() {
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2477,16 +2477,18 @@ static const JSFunctionSpec intrinsic_fu
JS_FN("intl_FormatDateTime", intl_FormatDateTime, 2,0),
JS_FN("intl_FormatNumber", intl_FormatNumber, 2,0),
JS_FN("intl_GetCalendarInfo", intl_GetCalendarInfo, 1,0),
JS_FN("intl_IsValidTimeZoneName", intl_IsValidTimeZoneName, 1,0),
JS_FN("intl_NumberFormat", intl_NumberFormat, 2,0),
JS_FN("intl_NumberFormat_availableLocales", intl_NumberFormat_availableLocales, 0,0),
JS_FN("intl_numberingSystem", intl_numberingSystem, 1,0),
JS_FN("intl_patternForSkeleton", intl_patternForSkeleton, 2,0),
+ JS_FN("intl_ListFormat_availableLocales", intl_ListFormat_availableLocales, 0, 0),
+ JS_FN("intl_FormatListFormat", intl_FormatListFormat, 2, 0),
JS_INLINABLE_FN("IsRegExpObject",
intrinsic_IsInstanceOfBuiltin<RegExpObject>, 1,0,
IsRegExpObject),
JS_FN("CallRegExpMethodIfWrapped",
CallNonGenericSelfhostedMethod<Is<RegExpObject>>, 2,0),
JS_INLINABLE_FN("RegExpMatcher", RegExpMatcher, 4,0,
RegExpMatcher),