Bug 1288457 - Part 5: Change Intl.PluralRules to use ClassSpec. r=mgaudet
authorAndré Bargull <andre.bargull@gmail.com>
Wed, 16 Oct 2019 12:31:58 +0000
changeset 559198 6d262e7942beae4bfa890cefaedea1b8546a0254
parent 559197 f464ebe632fd7d28ab0ee09461afe4c114235467
child 559199 4c8e2c07fa6398e1cc9c332b1b51d47398b522b0
push id12175
push userccoroiu@mozilla.com
push dateThu, 17 Oct 2019 19:29:09 +0000
treeherdermozilla-beta@d333b6ef1fd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmgaudet
bugs1288457
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1288457 - Part 5: Change Intl.PluralRules to use ClassSpec. r=mgaudet Differential Revision: https://phabricator.services.mozilla.com/D42874
js/public/Class.h
js/public/ProtoKey.h
js/src/builtin/intl/IntlObject.cpp
js/src/builtin/intl/PluralRules.cpp
js/src/builtin/intl/PluralRules.h
js/src/vm/CommonPropertyNames.h
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -745,17 +745,17 @@ static const uint32_t JSCLASS_FOREGROUND
 // 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.
 static const uint32_t JSCLASS_GLOBAL_APPLICATION_SLOTS = 5;
 static const uint32_t JSCLASS_GLOBAL_SLOT_COUNT =
-    JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 34;
+    JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 2 + 33;
 
 #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/public/ProtoKey.h
+++ b/js/public/ProtoKey.h
@@ -128,17 +128,18 @@
   IMAGINARY(WasmModule, dummy, dummy)                                        \
   IMAGINARY(WasmInstance, dummy, dummy)                                      \
   IMAGINARY(WasmMemory, dummy, dummy)                                        \
   IMAGINARY(WasmTable, dummy, dummy)                                         \
   IMAGINARY(WasmGlobal, dummy, dummy)                                        \
   REAL_IF_INTL(Collator, InitViaClassSpec, OCLASP(Collator))                 \
   REAL_IF_INTL(DateTimeFormat, InitViaClassSpec, OCLASP(DateTimeFormat))     \
   REAL_IF_INTL(Locale, InitViaClassSpec, OCLASP(Locale))                     \
-  REAL_IF_INTL(NumberFormat, InitViaClassSpec, OCLASP(NumberFormat))
+  REAL_IF_INTL(NumberFormat, InitViaClassSpec, OCLASP(NumberFormat))         \
+  REAL_IF_INTL(PluralRules, InitViaClassSpec, OCLASP(PluralRules))
 
 #define JS_FOR_PROTOTYPES(REAL, IMAGINARY)                      \
   JS_FOR_PROTOTYPES_(REAL, IMAGINARY, IF_INTL(REAL, IMAGINARY), \
                      IF_TYPEDOBJ(REAL, IMAGINARY), IF_SAB(REAL, IMAGINARY))
 
 #define JS_FOR_EACH_PROTOTYPE(MACRO) JS_FOR_PROTOTYPES(MACRO, MACRO)
 
 #endif /* js_ProtoKey_h */
--- a/js/src/builtin/intl/IntlObject.cpp
+++ b/js/src/builtin/intl/IntlObject.cpp
@@ -828,19 +828,17 @@ bool GlobalObject::initIntlObject(JSCont
     return false;
   }
   if (!CreateDateTimeFormat(cx, intl)) {
     return false;
   }
   if (!CreateNumberFormat(cx, intl)) {
     return false;
   }
-  RootedObject pluralRulesProto(cx,
-                                CreatePluralRulesPrototype(cx, intl, global));
-  if (!pluralRulesProto) {
+  if (!CreatePluralRules(cx, intl)) {
     return false;
   }
   RootedObject relativeTimeFmtProto(
       cx, CreateRelativeTimeFormatPrototype(cx, intl, global));
   if (!relativeTimeFmtProto) {
     return false;
   }
 
@@ -855,17 +853,16 @@ bool GlobalObject::initIntlObject(JSCont
   // in all relevant reserved global slots.
 
   // Cache the various prototypes, for use in creating instances of these
   // 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(PLURAL_RULES_PROTO, ObjectValue(*pluralRulesProto));
   global->setReservedSlot(RELATIVE_TIME_FORMAT_PROTO,
                           ObjectValue(*relativeTimeFmtProto));
 
   // 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.
--- a/js/src/builtin/intl/PluralRules.cpp
+++ b/js/src/builtin/intl/PluralRules.cpp
@@ -44,17 +44,19 @@ const JSClassOps PluralRulesObject::clas
                                                  nullptr, /* resolve */
                                                  nullptr, /* mayResolve */
                                                  PluralRulesObject::finalize};
 
 const JSClass PluralRulesObject::class_ = {
     js_Object_str,
     JSCLASS_HAS_RESERVED_SLOTS(PluralRulesObject::SLOT_COUNT) |
         JSCLASS_FOREGROUND_FINALIZE,
-    &PluralRulesObject::classOps_};
+    &PluralRulesObject::classOps_, &PluralRulesObject::classSpec_};
+
+const JSClass& PluralRulesObject::protoClass_ = PlainObject::class_;
 
 static bool pluralRules_toSource(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   args.rval().setString(cx->names().PluralRules);
   return true;
 }
 
 static const JSFunctionSpec pluralRules_static_methods[] = {
@@ -63,31 +65,44 @@ static const JSFunctionSpec pluralRules_
     JS_FS_END};
 
 static const JSFunctionSpec pluralRules_methods[] = {
     JS_SELF_HOSTED_FN("resolvedOptions", "Intl_PluralRules_resolvedOptions", 0,
                       0),
     JS_SELF_HOSTED_FN("select", "Intl_PluralRules_select", 1, 0),
     JS_FN(js_toSource_str, pluralRules_toSource, 0, 0), JS_FS_END};
 
+static bool PluralRules(JSContext* cx, unsigned argc, Value* vp);
+
+const ClassSpec PluralRulesObject::classSpec_ = {
+    GenericCreateConstructor<PluralRules, 0, gc::AllocKind::FUNCTION>,
+    GenericCreatePrototype<PluralRulesObject>,
+    pluralRules_static_methods,
+    nullptr,
+    pluralRules_methods,
+    nullptr,
+    nullptr,
+    ClassSpec::DontDefineConstructor};
+
 /**
  * PluralRules constructor.
  * Spec: ECMAScript 402 API, PluralRules, 13.2.1
  */
 static bool PluralRules(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
   // Step 1.
   if (!ThrowIfNotConstructing(cx, args, "Intl.PluralRules")) {
     return false;
   }
 
   // Step 2 (Inlined 9.1.14, OrdinaryCreateFromConstructor).
   RootedObject proto(cx);
-  if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_Null, &proto)) {
+  if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_PluralRules,
+                                          &proto)) {
     return false;
   }
 
   if (!proto) {
     proto = GlobalObject::getOrCreatePluralRulesPrototype(cx, cx->global());
     if (!proto) {
       return false;
     }
@@ -127,49 +142,25 @@ void js::PluralRulesObject::finalize(JSF
   if (nf) {
     unumf_close(nf);
   }
   if (formatted) {
     unumf_closeResult(formatted);
   }
 }
 
-JSObject* js::CreatePluralRulesPrototype(JSContext* cx, HandleObject Intl,
-                                         Handle<GlobalObject*> global) {
-  RootedFunction ctor(cx);
-  ctor =
-      global->createConstructor(cx, &PluralRules, cx->names().PluralRules, 0);
+bool js::CreatePluralRules(JSContext* cx, HandleObject Intl) {
+  JSObject* ctor =
+      GlobalObject::getOrCreateConstructor(cx, JSProto_PluralRules);
   if (!ctor) {
-    return nullptr;
-  }
-
-  RootedObject proto(
-      cx, GlobalObject::createBlankPrototype<PlainObject>(cx, global));
-  if (!proto) {
-    return nullptr;
-  }
-
-  if (!LinkConstructorAndPrototype(cx, ctor, proto)) {
-    return nullptr;
-  }
-
-  if (!JS_DefineFunctions(cx, ctor, pluralRules_static_methods)) {
-    return nullptr;
-  }
-
-  if (!JS_DefineFunctions(cx, proto, pluralRules_methods)) {
-    return nullptr;
+    return false;
   }
 
   RootedValue ctorValue(cx, ObjectValue(*ctor));
-  if (!DefineDataProperty(cx, Intl, cx->names().PluralRules, ctorValue, 0)) {
-    return nullptr;
-  }
-
-  return proto;
+  return DefineDataProperty(cx, Intl, cx->names().PluralRules, ctorValue, 0);
 }
 
 /**
  * This creates a new UNumberFormatter with calculated digit formatting
  * properties for PluralRules.
  *
  * This is similar to NewUNumberFormatter but doesn't allow for currency or
  * percent types.
--- a/js/src/builtin/intl/PluralRules.h
+++ b/js/src/builtin/intl/PluralRules.h
@@ -18,16 +18,17 @@ struct UFormattedNumber;
 struct UNumberFormatter;
 struct UPluralRules;
 
 namespace js {
 
 class PluralRulesObject : public NativeObject {
  public:
   static const JSClass class_;
+  static const JSClass& protoClass_;
 
   static constexpr uint32_t INTERNALS_SLOT = 0;
   static constexpr uint32_t UPLURAL_RULES_SLOT = 1;
   static constexpr uint32_t UNUMBER_FORMATTER_SLOT = 2;
   static constexpr uint32_t UFORMATTED_NUMBER_SLOT = 3;
   static constexpr uint32_t SLOT_COUNT = 4;
 
   static_assert(INTERNALS_SLOT == INTL_INTERNALS_OBJECT_SLOT,
@@ -67,23 +68,22 @@ class PluralRulesObject : public NativeO
   }
 
   void setFormattedNumber(UFormattedNumber* formatted) {
     setFixedSlot(UFORMATTED_NUMBER_SLOT, PrivateValue(formatted));
   }
 
  private:
   static const JSClassOps classOps_;
+  static const ClassSpec classSpec_;
 
   static void finalize(JSFreeOp* fop, JSObject* obj);
 };
 
-extern JSObject* CreatePluralRulesPrototype(JSContext* cx,
-                                            JS::Handle<JSObject*> Intl,
-                                            JS::Handle<GlobalObject*> global);
+extern bool CreatePluralRules(JSContext* cx, JS::Handle<JSObject*> Intl);
 
 /**
  * Returns a plural rule for the number x according to the effective
  * locale and the formatting options of the given PluralRules.
  *
  * A plural rule is a grammatical category that expresses count distinctions
  * (such as "one", "two", "few" etc.).
  *
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -336,17 +336,16 @@
   MACRO(outOfMemory, outOfMemory, "out of memory")                             \
   MACRO(ownKeys, ownKeys, "ownKeys")                                           \
   MACRO(Object_valueOf, Object_valueOf, "Object_valueOf")                      \
   MACRO(package, package, "package")                                           \
   MACRO(parseFloat, parseFloat, "parseFloat")                                  \
   MACRO(parseInt, parseInt, "parseInt")                                        \
   MACRO(pattern, pattern, "pattern")                                           \
   MACRO(pending, pending, "pending")                                           \
-  MACRO(PluralRules, PluralRules, "PluralRules")                               \
   MACRO(percentSign, percentSign, "percentSign")                               \
   MACRO(plusSign, plusSign, "plusSign")                                        \
   MACRO(public, public_, "public")                                             \
   MACRO(pull, pull, "pull")                                                    \
   MACRO(preventExtensions, preventExtensions, "preventExtensions")             \
   MACRO(private, private_, "private")                                          \
   MACRO(promise, promise, "promise")                                           \
   MACRO(propertyIsEnumerable, propertyIsEnumerable, "propertyIsEnumerable")    \
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -14,16 +14,17 @@
 #include "builtin/BigInt.h"
 #include "builtin/DataViewObject.h"
 #include "builtin/Eval.h"
 #ifdef ENABLE_INTL_API
 #  include "builtin/intl/Collator.h"
 #  include "builtin/intl/DateTimeFormat.h"
 #  include "builtin/intl/Locale.h"
 #  include "builtin/intl/NumberFormat.h"
+#  include "builtin/intl/PluralRules.h"
 #endif
 #include "builtin/MapObject.h"
 #include "builtin/ModuleObject.h"
 #include "builtin/Object.h"
 #include "builtin/Promise.h"
 #include "builtin/RegExp.h"
 #include "builtin/SelfHostingDefines.h"
 #include "builtin/Stream.h"
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -83,17 +83,16 @@ class GlobalObject : public NativeObject
     ASYNC_FUNCTION,
     ASYNC_ITERATOR_PROTO,
     ASYNC_FROM_SYNC_ITERATOR_PROTO,
     ASYNC_GENERATOR,
     ASYNC_GENERATOR_FUNCTION,
     ASYNC_GENERATOR_PROTO,
     MAP_ITERATOR_PROTO,
     SET_ITERATOR_PROTO,
-    PLURAL_RULES_PROTO,
     RELATIVE_TIME_FORMAT_PROTO,
     MODULE_PROTO,
     IMPORT_ENTRY_PROTO,
     EXPORT_ENTRY_PROTO,
     REQUESTED_MODULE_PROTO,
     REGEXP_STATICS,
     RUNTIME_CODEGEN_ENABLED,
     DEBUGGERS,
@@ -537,17 +536,20 @@ class GlobalObject : public NativeObject
     if (!ensureConstructor(cx, global, JSProto_DateTimeFormat)) {
       return nullptr;
     }
     return &global->getPrototype(JSProto_DateTimeFormat).toObject();
   }
 
   static JSObject* getOrCreatePluralRulesPrototype(
       JSContext* cx, Handle<GlobalObject*> global) {
-    return getOrCreateObject(cx, global, PLURAL_RULES_PROTO, initIntlObject);
+    if (!ensureConstructor(cx, global, JSProto_PluralRules)) {
+      return nullptr;
+    }
+    return &global->getPrototype(JSProto_PluralRules).toObject();
   }
 
   static JSObject* getOrCreateRelativeTimeFormatPrototype(
       JSContext* cx, Handle<GlobalObject*> global) {
     return getOrCreateObject(cx, global, RELATIVE_TIME_FORMAT_PROTO,
                              initIntlObject);
   }