Bug 1325459 - Expose PluralRules via addIntlExtras.
MozReview-Commit-ID: DNLOlaH6Og8
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -3751,17 +3751,17 @@ pluralRules_finalize(FreeOp* fop, JSObje
// containing a private. See bug 949220.
const Value& slot = obj->as<NativeObject>().getReservedSlot(UPLURAL_RULES_SLOT);
if (!slot.isUndefined()) {
if (UPluralRules* pr = static_cast<UPluralRules*>(slot.toPrivate()))
uplrules_close(pr);
}
}
-static JSObject*
+JSObject*
CreatePluralRulesPrototype(JSContext* cx, HandleObject Intl, Handle<GlobalObject*> global)
{
RootedFunction ctor(cx);
ctor = global->createConstructor(cx, &PluralRules, cx->names().PluralRules, 0);
if (!ctor)
return nullptr;
RootedNativeObject proto(cx, global->createBlankPrototype(cx, &PluralRulesClass));
@@ -4486,19 +4486,16 @@ 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 pluralRulesProto(cx, CreatePluralRulesPrototype(cx, intl, global));
- if (!pluralRulesProto)
- 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;
}
@@ -4510,17 +4507,16 @@ 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(PLURAL_RULES_PROTO, ObjectValue(*pluralRulesProto));
// 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
@@ -501,13 +501,21 @@ UCharToChar16(UChar* chars)
return reinterpret_cast<char16_t*>(chars);
}
inline const char16_t*
UCharToChar16(const UChar* chars)
{
return reinterpret_cast<const char16_t*>(chars);
}
+
#endif // ENABLE_INTL_API
} // namespace js
+#if ENABLE_INTL_API
+
+extern JSObject*
+CreatePluralRulesPrototype(JSContext* cx, js::HandleObject Intl, js::Handle<js::GlobalObject*> global);
+
+#endif // ENABLE_INTL_API
+
#endif /* builtin_Intl_h */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -57,16 +57,17 @@
#include "jstypes.h"
#include "jsutil.h"
#ifdef XP_WIN
# include "jswin.h"
#endif
#include "jswrapper.h"
#include "shellmoduleloader.out.h"
+#include "builtin/Intl.h"
#include "builtin/ModuleObject.h"
#include "builtin/TestingFunctions.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"
@@ -82,16 +83,17 @@
#include "shell/OSObject.h"
#include "threading/ConditionVariable.h"
#include "threading/LockGuard.h"
#include "threading/Thread.h"
#include "vm/ArgumentsObject.h"
#include "vm/AsyncFunction.h"
#include "vm/Compression.h"
#include "vm/Debugger.h"
+#include "vm/GlobalObject.h"
#include "vm/HelperThreads.h"
#include "vm/Monitor.h"
#include "vm/MutexIDs.h"
#include "vm/Shape.h"
#include "vm/SharedArrayObject.h"
#include "vm/StringBuffer.h"
#include "vm/Time.h"
#include "vm/TypedArrayObject.h"
@@ -895,16 +897,22 @@ AddIntlExtras(JSContext* cx, unsigned ar
JS_SELF_HOSTED_FN("getCalendarInfo", "Intl_getCalendarInfo", 1, 0),
JS_SELF_HOSTED_FN("getDisplayNames", "Intl_getDisplayNames", 2, 0),
JS_FS_END
};
if (!JS_DefineFunctions(cx, intl, funcs))
return false;
+ RootedObject pluralRulesProto(cx, CreatePluralRulesPrototype(cx, intl, cx->global()));
+ if (!pluralRulesProto)
+ return false;
+
+ cx->global()->setReservedSlot(GlobalObject::PLURAL_RULES_PROTO, ObjectValue(*pluralRulesProto));
+
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/tests/Intl/PluralRules/pluralrules.js
+++ b/js/src/tests/Intl/PluralRules/pluralrules.js
@@ -1,17 +1,19 @@
-// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+// |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 format function with a diverse set of locales and options.
var pr;
+addIntlExtras(Intl);
+
pr = new Intl.PluralRules("en-us");
assertEq(pr.resolvedOptions().locale, "en-US");
assertEq(pr.resolvedOptions().type, "cardinal");
assertEq(pr.resolvedOptions().pluralCategories.length, 2);
pr = new Intl.PluralRules("de", {type: 'cardinal'});
assertEq(pr.resolvedOptions().pluralCategories.length, 2);
--- a/js/src/tests/Intl/PluralRules/select.js
+++ b/js/src/tests/Intl/PluralRules/select.js
@@ -1,17 +1,19 @@
-// |reftest| skip-if(!this.hasOwnProperty("Intl"))
+// |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 format function with a diverse set of locales and options.
var pr;
+addIntlExtras(Intl);
+
pr = new Intl.PluralRules("en-us");
assertEq(pr.select(0), "other");
assertEq(pr.select(0.5), "other");
assertEq(pr.select(1.2), "other");
assertEq(pr.select(1.5), "other");
assertEq(pr.select(1.7), "other");
assertEq(pr.select(-1), "one");
assertEq(pr.select(1), "one");
--- a/js/src/tests/Intl/PluralRules/supportedLocalesOf.js
+++ b/js/src/tests/Intl/PluralRules/supportedLocalesOf.js
@@ -1,9 +1,9 @@
-// |reftest| skip-if(!this.hasOwnProperty("Intl")||xulRuntime.shell)
+// |reftest| skip-if(!this.hasOwnProperty('Intl')||!this.hasOwnProperty('addIntlExtras')||xulRuntime.shell)
// -- test in browser only that ICU has locale data for all Mozilla languages
/* 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/. */
// This array contains the locales that ICU supports in
// number formatting whose languages Mozilla localizes Firefox into.
@@ -361,13 +361,15 @@ var locales = [
"zh-Hans-MO",
"zh-Hans-SG",
"zh-Hant",
"zh-Hant-HK",
"zh-Hant-MO",
"zh-Hant-TW",
];
+addIntlExtras(Intl);
+
const result = Intl.PluralRules.supportedLocalesOf(locales);
assertEqArray(locales, result);
reportCompare(0, 0, 'ok');
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -62,16 +62,29 @@ class GlobalObject : public NativeObject
static const unsigned APPLICATION_SLOTS = JSCLASS_GLOBAL_APPLICATION_SLOTS;
/*
* Count of slots to store built-in prototypes and initial visible
* properties for the constructors.
*/
static const unsigned STANDARD_CLASS_SLOTS = JSProto_LIMIT * 2;
+ enum WarnOnceFlag : int32_t {
+ WARN_WATCH_DEPRECATED = 1 << 0,
+ };
+
+ // Emit the specified warning if the given slot in |obj|'s global isn't
+ // true, then set the slot to true. Thus calling this method warns once
+ // for each global object it's called on, and every other call does
+ // nothing.
+ static bool
+ warnOnceAbout(JSContext* cx, HandleObject obj, WarnOnceFlag flag, unsigned errorNumber);
+
+
+ public:
enum : unsigned {
/* Various function values needed by the engine. */
EVAL = APPLICATION_SLOTS + STANDARD_CLASS_SLOTS,
CREATE_DATAVIEW_FOR_THIS,
THROWTYPEERROR,
/*
* Instances of the internal createArrayFromBuffer function used by the
@@ -124,29 +137,17 @@ class GlobalObject : public NativeObject
/*
* The slot count must be in the public API for JSCLASS_GLOBAL_FLAGS, and
* we won't expose GlobalObject, so just assert that the two values are
* synchronized.
*/
static_assert(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS,
"global object slot counts are inconsistent");
- enum WarnOnceFlag : int32_t {
- WARN_WATCH_DEPRECATED = 1 << 0,
- };
- // Emit the specified warning if the given slot in |obj|'s global isn't
- // true, then set the slot to true. Thus calling this method warns once
- // for each global object it's called on, and every other call does
- // nothing.
- static bool
- warnOnceAbout(JSContext* cx, HandleObject obj, WarnOnceFlag flag, unsigned errorNumber);
-
-
- public:
LexicalEnvironmentObject& lexicalEnvironment() const;
GlobalScope& emptyGlobalScope() const;
void setThrowTypeError(JSFunction* fun) {
MOZ_ASSERT(getSlotRef(THROWTYPEERROR).isUndefined());
setSlot(THROWTYPEERROR, ObjectValue(*fun));
}