Bug 1288457 - Part 7: Remove boilerplate to create Intl constructors. r=mgaudet
authorAndré Bargull <andre.bargull@gmail.com>
Wed, 16 Oct 2019 12:34:02 +0000
changeset 559200 e3e22cb993b378664bc453a473f805127768e8d4
parent 559199 4c8e2c07fa6398e1cc9c332b1b51d47398b522b0
child 559201 673dac1119b6428329be9627ff3ad69019d92a70
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 7: Remove boilerplate to create Intl constructors. r=mgaudet - Remove the various `js::CreateXYZ` functions be directly iterating over the JSProtoKeys in `js::InitIntlClass`. - Also remove the unused `GlobalObject::getOrCreateIntlObject` method and then merge `GlobalObject::initIntlObject` with `js::InitIntlClass`. Differential Revision: https://phabricator.services.mozilla.com/D42876
js/src/builtin/intl/Collator.cpp
js/src/builtin/intl/Collator.h
js/src/builtin/intl/DateTimeFormat.cpp
js/src/builtin/intl/DateTimeFormat.h
js/src/builtin/intl/IntlObject.cpp
js/src/builtin/intl/Locale.cpp
js/src/builtin/intl/Locale.h
js/src/builtin/intl/NumberFormat.cpp
js/src/builtin/intl/NumberFormat.h
js/src/builtin/intl/PluralRules.cpp
js/src/builtin/intl/PluralRules.h
js/src/builtin/intl/RelativeTimeFormat.cpp
js/src/builtin/intl/RelativeTimeFormat.h
js/src/vm/GlobalObject.h
--- a/js/src/builtin/intl/Collator.cpp
+++ b/js/src/builtin/intl/Collator.cpp
@@ -144,27 +144,16 @@ bool js::intl_Collator(JSContext* cx, un
 void js::CollatorObject::finalize(JSFreeOp* fop, JSObject* obj) {
   MOZ_ASSERT(fop->onMainThread());
 
   if (UCollator* coll = obj->as<CollatorObject>().getCollator()) {
     ucol_close(coll);
   }
 }
 
-bool js::CreateCollator(JSContext* cx, HandleObject Intl) {
-  JSObject* ctor = GlobalObject::getOrCreateConstructor(cx, JSProto_Collator);
-  if (!ctor) {
-    return false;
-  }
-
-  // 8.1
-  RootedValue ctorValue(cx, ObjectValue(*ctor));
-  return DefineDataProperty(cx, Intl, cx->names().Collator, ctorValue, 0);
-}
-
 bool js::intl_availableCollations(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   MOZ_ASSERT(args.length() == 1);
   MOZ_ASSERT(args[0].isString());
 
   UniqueChars locale = intl::EncodeLocale(cx, args[0].toString());
   if (!locale) {
     return false;
--- a/js/src/builtin/intl/Collator.h
+++ b/js/src/builtin/intl/Collator.h
@@ -48,18 +48,16 @@ class CollatorObject : public NativeObje
 
  private:
   static const JSClassOps classOps_;
   static const ClassSpec classSpec_;
 
   static void finalize(JSFreeOp* fop, JSObject* obj);
 };
 
-extern bool CreateCollator(JSContext* cx, JS::Handle<JSObject*> Intl);
-
 /**
  * Returns a new instance of the standard built-in Collator constructor.
  * 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: collator = intl_Collator(locales, options)
  */
 extern MOZ_MUST_USE bool intl_Collator(JSContext* cx, unsigned argc,
--- a/js/src/builtin/intl/DateTimeFormat.cpp
+++ b/js/src/builtin/intl/DateTimeFormat.cpp
@@ -177,28 +177,16 @@ bool js::intl_DateTimeFormat(JSContext* 
 void js::DateTimeFormatObject::finalize(JSFreeOp* fop, JSObject* obj) {
   MOZ_ASSERT(fop->onMainThread());
 
   if (UDateFormat* df = obj->as<DateTimeFormatObject>().getDateFormat()) {
     udat_close(df);
   }
 }
 
-bool js::CreateDateTimeFormat(JSContext* cx, JS::Handle<JSObject*> Intl) {
-  JSObject* ctor =
-      GlobalObject::getOrCreateConstructor(cx, JSProto_DateTimeFormat);
-  if (!ctor) {
-    return false;
-  }
-
-  // 8.1
-  RootedValue ctorValue(cx, ObjectValue(*ctor));
-  return DefineDataProperty(cx, Intl, cx->names().DateTimeFormat, ctorValue, 0);
-}
-
 bool js::AddMozDateTimeFormatConstructor(JSContext* cx,
                                          JS::Handle<JSObject*> intl) {
   RootedObject ctor(
       cx, GlobalObject::createConstructor(cx, MozDateTimeFormat,
                                           cx->names().DateTimeFormat, 0));
   if (!ctor) {
     return false;
   }
--- a/js/src/builtin/intl/DateTimeFormat.h
+++ b/js/src/builtin/intl/DateTimeFormat.h
@@ -46,18 +46,16 @@ class DateTimeFormatObject : public Nati
 
  private:
   static const JSClassOps classOps_;
   static const ClassSpec classSpec_;
 
   static void finalize(JSFreeOp* fop, JSObject* obj);
 };
 
-extern bool CreateDateTimeFormat(JSContext* cx, JS::Handle<JSObject*> Intl);
-
 /**
  * Returns a new instance of the standard built-in DateTimeFormat constructor.
  * 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: dateTimeFormat = intl_DateTimeFormat(locales, options)
  */
 extern MOZ_MUST_USE bool intl_DateTimeFormat(JSContext* cx, unsigned argc,
--- a/js/src/builtin/intl/IntlObject.cpp
+++ b/js/src/builtin/intl/IntlObject.cpp
@@ -33,16 +33,17 @@
 #include "js/Result.h"
 #include "js/StableStringChars.h"
 #include "unicode/ucal.h"
 #include "unicode/udat.h"
 #include "unicode/udatpg.h"
 #include "unicode/uloc.h"
 #include "unicode/utypes.h"
 #include "vm/GlobalObject.h"
+#include "vm/JSAtom.h"
 #include "vm/JSContext.h"
 #include "vm/JSObject.h"
 #include "vm/StringType.h"
 
 #include "vm/JSObject-inl.h"
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
@@ -797,67 +798,59 @@ static const JSFunctionSpec intl_static_
     JS_FN(js_toSource_str, intl_toSource, 0, 0),
     JS_SELF_HOSTED_FN("getCanonicalLocales", "Intl_getCanonicalLocales", 1, 0),
     JS_FS_END};
 
 /**
  * Initializes the Intl Object and its standard built-in properties.
  * Spec: ECMAScript Internationalization API Specification, 8.0, 8.1
  */
-/* static */
-bool GlobalObject::initIntlObject(JSContext* cx, Handle<GlobalObject*> global) {
+JSObject* js::InitIntlClass(JSContext* cx, Handle<GlobalObject*> global) {
   RootedObject proto(cx, GlobalObject::getOrCreateObjectPrototype(cx, global));
   if (!proto) {
-    return false;
+    return nullptr;
   }
 
   // The |Intl| object is just a plain object with some "static" function
   // properties and some constructor properties.
   RootedObject intl(
       cx, NewObjectWithGivenProto(cx, &IntlClass, proto, SingletonObject));
   if (!intl) {
-    return false;
+    return nullptr;
   }
 
   // Add the static functions.
   if (!JS_DefineFunctions(cx, intl, intl_static_methods)) {
-    return false;
+    return nullptr;
   }
 
-  // Add the constructor properties, computing and returning the relevant
-  // prototype objects needed below.
-  if (!CreateCollator(cx, intl)) {
-    return false;
-  }
-  if (!CreateDateTimeFormat(cx, intl)) {
-    return false;
-  }
-  if (!CreateNumberFormat(cx, intl)) {
-    return false;
-  }
-  if (!CreatePluralRules(cx, intl)) {
-    return false;
-  }
-  if (!CreateRelativeTimeFormat(cx, intl)) {
-    return false;
+  // Add the constructor properties.
+  RootedId ctorId(cx);
+  RootedValue ctorValue(cx);
+  for (const auto& protoKey :
+       {JSProto_Collator, JSProto_DateTimeFormat, JSProto_NumberFormat,
+        JSProto_PluralRules, JSProto_RelativeTimeFormat}) {
+    JSObject* ctor = GlobalObject::getOrCreateConstructor(cx, protoKey);
+    if (!ctor) {
+      return nullptr;
+    }
+
+    ctorId = NameToId(ClassName(protoKey, cx));
+    ctorValue.setObject(*ctor);
+    if (!DefineDataProperty(cx, intl, ctorId, ctorValue, 0)) {
+      return nullptr;
+    }
   }
 
   // The |Intl| object is fully set up now, so define the global property.
   RootedValue intlValue(cx, ObjectValue(*intl));
   if (!DefineDataProperty(cx, global, cx->names().Intl, intlValue,
                           JSPROP_RESOLVING)) {
-    return false;
+    return nullptr;
   }
 
   // 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|.
   global->setConstructor(JSProto_Intl, ObjectValue(*intl));
-  return true;
+
+  return intl;
 }
-
-JSObject* js::InitIntlClass(JSContext* cx, Handle<GlobalObject*> global) {
-  if (!GlobalObject::initIntlObject(cx, global)) {
-    return nullptr;
-  }
-
-  return &global->getConstructor(JSProto_Intl).toObject();
-}
--- a/js/src/builtin/intl/Locale.cpp
+++ b/js/src/builtin/intl/Locale.cpp
@@ -1238,28 +1238,24 @@ const ClassSpec LocaleObject::classSpec_
     GenericCreatePrototype<LocaleObject>,
     nullptr,
     nullptr,
     locale_methods,
     locale_properties,
     nullptr,
     ClassSpec::DontDefineConstructor};
 
-bool js::CreateLocale(JSContext* cx, HandleObject Intl) {
+bool js::AddLocaleConstructor(JSContext* cx, JS::Handle<JSObject*> intl) {
   JSObject* ctor = GlobalObject::getOrCreateConstructor(cx, JSProto_Locale);
   if (!ctor) {
     return false;
   }
 
   RootedValue ctorValue(cx, ObjectValue(*ctor));
-  return DefineDataProperty(cx, Intl, cx->names().Locale, ctorValue, 0);
-}
-
-bool js::AddLocaleConstructor(JSContext* cx, JS::Handle<JSObject*> intl) {
-  return CreateLocale(cx, intl);
+  return DefineDataProperty(cx, intl, cx->names().Locale, ctorValue, 0);
 }
 
 bool js::intl_ValidateAndCanonicalizeLanguageTag(JSContext* cx, unsigned argc,
                                                  Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   MOZ_ASSERT(args.length() == 2);
 
   HandleValue tagValue = args[0];
--- a/js/src/builtin/intl/Locale.h
+++ b/js/src/builtin/intl/Locale.h
@@ -42,18 +42,16 @@ class LocaleObject : public NativeObject
   const Value& unicodeExtension() const {
     return getFixedSlot(UNICODE_EXTENSION_SLOT);
   }
 
  private:
   static const ClassSpec classSpec_;
 };
 
-extern bool CreateLocale(JSContext* cx, JS::Handle<JSObject*> Intl);
-
 extern MOZ_MUST_USE bool intl_ValidateAndCanonicalizeLanguageTag(JSContext* cx,
                                                                  unsigned argc,
                                                                  Value* vp);
 
 extern MOZ_MUST_USE bool intl_TryValidateAndCanonicalizeLanguageTag(
     JSContext* cx, unsigned argc, Value* vp);
 
 }  // namespace js
--- a/js/src/builtin/intl/NumberFormat.cpp
+++ b/js/src/builtin/intl/NumberFormat.cpp
@@ -178,28 +178,16 @@ void js::NumberFormatObject::finalize(JS
   if (nf) {
     unumf_close(nf);
   }
   if (formatted) {
     unumf_closeResult(formatted);
   }
 }
 
-bool js::CreateNumberFormat(JSContext* cx, HandleObject Intl) {
-  JSObject* ctor =
-      GlobalObject::getOrCreateConstructor(cx, JSProto_NumberFormat);
-  if (!ctor) {
-    return false;
-  }
-
-  // 8.1
-  RootedValue ctorValue(cx, ObjectValue(*ctor));
-  return DefineDataProperty(cx, Intl, cx->names().NumberFormat, ctorValue, 0);
-}
-
 bool js::intl_numberingSystem(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   MOZ_ASSERT(args.length() == 1);
   MOZ_ASSERT(args[0].isString());
 
   UniqueChars locale = intl::EncodeLocale(cx, args[0].toString());
   if (!locale) {
     return false;
--- a/js/src/builtin/intl/NumberFormat.h
+++ b/js/src/builtin/intl/NumberFormat.h
@@ -63,18 +63,16 @@ class NumberFormatObject : public Native
 
  private:
   static const JSClassOps classOps_;
   static const ClassSpec classSpec_;
 
   static void finalize(JSFreeOp* fop, JSObject* obj);
 };
 
-extern bool CreateNumberFormat(JSContext* cx, HandleObject Intl);
-
 /**
  * Returns a new instance of the standard built-in NumberFormat constructor.
  * 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: numberFormat = intl_NumberFormat(locales, options)
  */
 extern MOZ_MUST_USE bool intl_NumberFormat(JSContext* cx, unsigned argc,
--- a/js/src/builtin/intl/PluralRules.cpp
+++ b/js/src/builtin/intl/PluralRules.cpp
@@ -142,27 +142,16 @@ void js::PluralRulesObject::finalize(JSF
   if (nf) {
     unumf_close(nf);
   }
   if (formatted) {
     unumf_closeResult(formatted);
   }
 }
 
-bool js::CreatePluralRules(JSContext* cx, HandleObject Intl) {
-  JSObject* ctor =
-      GlobalObject::getOrCreateConstructor(cx, JSProto_PluralRules);
-  if (!ctor) {
-    return false;
-  }
-
-  RootedValue ctorValue(cx, ObjectValue(*ctor));
-  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.
  */
 static UNumberFormatter* NewUNumberFormatterForPluralRules(
--- a/js/src/builtin/intl/PluralRules.h
+++ b/js/src/builtin/intl/PluralRules.h
@@ -73,18 +73,16 @@ class PluralRulesObject : public NativeO
 
  private:
   static const JSClassOps classOps_;
   static const ClassSpec classSpec_;
 
   static void finalize(JSFreeOp* fop, JSObject* obj);
 };
 
-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.).
  *
  * Usage: rule = intl_SelectPluralRule(pluralRules, x)
--- a/js/src/builtin/intl/RelativeTimeFormat.cpp
+++ b/js/src/builtin/intl/RelativeTimeFormat.cpp
@@ -143,28 +143,16 @@ void js::RelativeTimeFormatObject::final
   MOZ_ASSERT(fop->onMainThread());
 
   if (URelativeDateTimeFormatter* rtf =
           obj->as<RelativeTimeFormatObject>().getRelativeDateTimeFormatter()) {
     ureldatefmt_close(rtf);
   }
 }
 
-bool js::CreateRelativeTimeFormat(JSContext* cx, HandleObject Intl) {
-  JSObject* ctor =
-      GlobalObject::getOrCreateConstructor(cx, JSProto_RelativeTimeFormat);
-  if (!ctor) {
-    return false;
-  }
-
-  RootedValue ctorValue(cx, ObjectValue(*ctor));
-  return DefineDataProperty(cx, Intl, cx->names().RelativeTimeFormat, ctorValue,
-                            0);
-}
-
 /**
  * Returns a new URelativeDateTimeFormatter with the locale and options of the
  * given RelativeTimeFormatObject.
  */
 static URelativeDateTimeFormatter* NewURelativeDateTimeFormatter(
     JSContext* cx, Handle<RelativeTimeFormatObject*> relativeTimeFormat) {
   RootedObject internals(cx, intl::GetInternalsObject(cx, relativeTimeFormat));
   if (!internals) {
--- a/js/src/builtin/intl/RelativeTimeFormat.h
+++ b/js/src/builtin/intl/RelativeTimeFormat.h
@@ -46,18 +46,16 @@ class RelativeTimeFormatObject : public 
 
  private:
   static const JSClassOps classOps_;
   static const ClassSpec classSpec_;
 
   static void finalize(JSFreeOp* fop, JSObject* obj);
 };
 
-extern bool CreateRelativeTimeFormat(JSContext* cx, JS::Handle<JSObject*> Intl);
-
 /**
  * Returns a relative time as a string formatted according to the effective
  * locale and the formatting options of the given RelativeTimeFormat.
  *
  * |t| should be a number representing a number to be formatted.
  * |unit| should be "second", "minute", "hour", "day", "week", "month",
  *                  "quarter", or "year".
  * |numeric| should be "always" or "auto".
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -463,24 +463,16 @@ class GlobalObject : public NativeObject
   static NativeObject* getOrCreateWeakSetPrototype(
       JSContext* cx, Handle<GlobalObject*> global) {
     if (!ensureConstructor(cx, global, JSProto_WeakSet)) {
       return nullptr;
     }
     return &global->getPrototype(JSProto_WeakSet).toObject().as<NativeObject>();
   }
 
-#if ENABLE_INTL_API
-  static JSObject* getOrCreateIntlObject(JSContext* cx,
-                                         Handle<GlobalObject*> global) {
-    return getOrCreateObject(cx, global, APPLICATION_SLOTS + JSProto_Intl,
-                             initIntlObject);
-  }
-#endif
-
   static JSObject* getOrCreateTypedObjectModule(JSContext* cx,
                                                 Handle<GlobalObject*> global) {
     return getOrCreateObject(cx, global,
                              APPLICATION_SLOTS + JSProto_TypedObject,
                              initTypedObjectModule);
   }
 
   static TypeDescr* getOrCreateScalarTypeDescr(JSContext* cx,
@@ -857,21 +849,16 @@ class GlobalObject : public NativeObject
   static bool initAsyncFunction(JSContext* cx, Handle<GlobalObject*> global);
 
   static bool initAsyncGenerators(JSContext* cx, Handle<GlobalObject*> global);
 
   // Implemented in builtin/MapObject.cpp.
   static bool initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
   static bool initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
 
-#ifdef ENABLE_INTL_API
-  // Implemented in builtin/intl/IntlObject.cpp.
-  static bool initIntlObject(JSContext* cx, Handle<GlobalObject*> global);
-#endif
-
   // Implemented in builtin/ModuleObject.cpp
   static bool initModuleProto(JSContext* cx, Handle<GlobalObject*> global);
   static bool initImportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
   static bool initExportEntryProto(JSContext* cx, Handle<GlobalObject*> global);
   static bool initRequestedModuleProto(JSContext* cx,
                                        Handle<GlobalObject*> global);
 
   // Implemented in builtin/TypedObject.cpp