tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GlobalObject.h (43748B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef vm_GlobalObject_h
      8 #define vm_GlobalObject_h
      9 
     10 #include "js/GlobalObject.h"
     11 
     12 #include "mozilla/Assertions.h"
     13 #include "mozilla/EnumeratedArray.h"
     14 
     15 #include <stdint.h>
     16 #include <type_traits>
     17 
     18 #include "jsexn.h"
     19 #include "jsfriendapi.h"
     20 #include "jspubtd.h"
     21 #include "jstypes.h"
     22 #include "NamespaceImports.h"
     23 
     24 #ifdef JS_HAS_INTL_API
     25 #  include "builtin/intl/GlobalIntlData.h"
     26 #endif
     27 #include "gc/AllocKind.h"
     28 #include "js/CallArgs.h"
     29 #include "js/Class.h"
     30 #include "js/ErrorReport.h"
     31 #include "js/PropertyDescriptor.h"
     32 #include "js/RootingAPI.h"
     33 #include "js/TypeDecls.h"
     34 #include "js/Value.h"
     35 #include "vm/ArrayObject.h"
     36 #include "vm/JSAtomState.h"
     37 #include "vm/JSContext.h"
     38 #include "vm/JSFunction.h"
     39 #include "vm/JSObject.h"
     40 #include "vm/NativeObject.h"
     41 #include "vm/Realm.h"
     42 #include "vm/RegExpShared.h"
     43 #include "vm/Shape.h"
     44 #include "vm/StringType.h"
     45 
     46 struct JSFunctionSpec;
     47 class JSJitInfo;
     48 struct JSPrincipals;
     49 struct JSPropertySpec;
     50 
     51 namespace JS {
     52 class JS_PUBLIC_API RealmOptions;
     53 };
     54 
     55 namespace js {
     56 
     57 class ArgumentsObject;
     58 class GlobalScope;
     59 class GlobalLexicalEnvironmentObject;
     60 class MapObject;
     61 class PlainObject;
     62 class PropertyIteratorObject;
     63 class RegExpStatics;
     64 class SetObject;
     65 
     66 // Fixed slot capacities for PlainObjects. The global has a cached Shape for
     67 // PlainObject with default prototype for each of these values.
     68 enum class PlainObjectSlotsKind {
     69  Slots0,
     70  Slots2,
     71  Slots4,
     72  Slots6,
     73  Slots8,
     74  Slots12,
     75  Slots16,
     76  Limit
     77 };
     78 
     79 static PlainObjectSlotsKind PlainObjectSlotsKindFromAllocKind(
     80    gc::AllocKind kind) {
     81  switch (kind) {
     82    case gc::AllocKind::OBJECT0:
     83      return PlainObjectSlotsKind::Slots0;
     84    case gc::AllocKind::OBJECT2:
     85      return PlainObjectSlotsKind::Slots2;
     86    case gc::AllocKind::OBJECT4:
     87      return PlainObjectSlotsKind::Slots4;
     88    case gc::AllocKind::OBJECT6:
     89      return PlainObjectSlotsKind::Slots6;
     90    case gc::AllocKind::OBJECT8:
     91      return PlainObjectSlotsKind::Slots8;
     92    case gc::AllocKind::OBJECT12:
     93      return PlainObjectSlotsKind::Slots12;
     94    case gc::AllocKind::OBJECT16:
     95      return PlainObjectSlotsKind::Slots16;
     96    default:
     97      break;
     98  }
     99  MOZ_CRASH("Invalid kind");
    100 }
    101 
    102 // Data attached to a GlobalObject. This is freed when clearing the Realm's
    103 // global_ only because this way we don't need to add a finalizer to all
    104 // GlobalObject JSClasses.
    105 class GlobalObjectData {
    106  friend class js::GlobalObject;
    107 
    108  GlobalObjectData(const GlobalObjectData&) = delete;
    109  void operator=(const GlobalObjectData&) = delete;
    110 
    111 public:
    112  explicit GlobalObjectData(Zone* zone);
    113 
    114  ~GlobalObjectData();
    115 
    116  // The original values for built-in constructors (with their prototype
    117  // objects) based on JSProtoKey.
    118  //
    119  // This is necessary to implement spec language speaking in terms of "the
    120  // original Array prototype object", or "as if by the expression new Array()"
    121  // referring to the original Array constructor. The actual (writable and even
    122  // deletable) Object, Array, &c. properties are not stored here.
    123  struct ConstructorWithProto {
    124    GCPtr<JSObject*> constructor;
    125    GCPtr<JSObject*> prototype;
    126  };
    127  using CtorArray = mozilla::EnumeratedArray<JSProtoKey, ConstructorWithProto,
    128                                             size_t(JSProto_LIMIT)>;
    129  CtorArray builtinConstructors;
    130 
    131  // Built-in prototypes for this global. Note that this is different from the
    132  // set of built-in constructors/prototypes based on JSProtoKey.
    133  enum class ProtoKind {
    134    ArrayIteratorProto,
    135    StringIteratorProto,
    136    RegExpStringIteratorProto,
    137    GeneratorObjectProto,
    138    AsyncIteratorProto,
    139    AsyncFromSyncIteratorProto,
    140    AsyncGeneratorProto,
    141    MapIteratorProto,
    142    SetIteratorProto,
    143    WrapForValidIteratorProto,
    144    IteratorHelperProto,
    145    AsyncIteratorHelperProto,
    146    SegmentsProto,
    147    SegmentIteratorProto,
    148 #ifdef NIGHTLY_BUILD
    149    IteratorRangeProto,
    150 #endif
    151    Limit
    152  };
    153  using ProtoArray = mozilla::EnumeratedArray<ProtoKind, GCPtr<JSObject*>,
    154                                              size_t(ProtoKind::Limit)>;
    155  ProtoArray builtinProtos;
    156 
    157  GCPtr<GlobalScope*> emptyGlobalScope;
    158 
    159  // The lexical environment for global let/const/class bindings.
    160  GCPtr<GlobalLexicalEnvironmentObject*> lexicalEnvironment;
    161 
    162  // The WindowProxy associated with this global.
    163  GCPtr<JSObject*> windowProxy;
    164 
    165  // Functions and other top-level values for self-hosted code. The "computed"
    166  // holder is used as the target of `SetIntrinsic` calls, but the same property
    167  // may also be cached on the normal intrinsics holder for `GetIntrinsic`.
    168  GCPtr<NativeObject*> intrinsicsHolder;
    169  GCPtr<NativeObject*> computedIntrinsicsHolder;
    170 
    171  // List of source URLs for this realm. This is used by the debugger.
    172  GCPtr<ArrayObject*> sourceURLsHolder;
    173 
    174  // Realm-specific object that can be used as key in WeakMaps.
    175  GCPtr<PlainObject*> realmKeyObject;
    176 
    177  // The unique %ThrowTypeError% function for this global.
    178  GCPtr<JSFunction*> throwTypeError;
    179 
    180  // The unique %eval% function (for indirect eval) for this global.
    181  GCPtr<JSFunction*> eval;
    182 
    183  // Empty iterator object used for for-in with null/undefined.
    184  GCPtr<PropertyIteratorObject*> emptyIterator;
    185 
    186  // Cached shape for new arrays with Array.prototype as prototype.
    187  GCPtr<SharedShape*> arrayShapeWithDefaultProto;
    188 
    189  // Shape for PlainObject with %Object.prototype% as proto, for each object
    190  // AllocKind.
    191  using PlainObjectShapeArray =
    192      mozilla::EnumeratedArray<PlainObjectSlotsKind, GCPtr<SharedShape*>,
    193                               size_t(PlainObjectSlotsKind::Limit)>;
    194  PlainObjectShapeArray plainObjectShapesWithDefaultProto;
    195 
    196  // Shape for JSFunction with %Function.prototype% as proto, for both
    197  // non-extended and extended functions.
    198  GCPtr<SharedShape*> functionShapeWithDefaultProto;
    199  GCPtr<SharedShape*> extendedFunctionShapeWithDefaultProto;
    200 
    201  // Shape for BoundFunctionObject with %Function.prototype% as proto.
    202  GCPtr<SharedShape*> boundFunctionShapeWithDefaultProto;
    203 
    204  // Shape for RegExpObject with %RegExp.prototype% as proto.
    205  GCPtr<SharedShape*> regExpShapeWithDefaultProto;
    206 
    207  // Global state for regular expressions.
    208  RegExpRealm regExpRealm;
    209 
    210 #ifdef JS_HAS_INTL_API
    211  // Cache Intl formatters.
    212  intl::GlobalIntlData globalIntlData;
    213 #endif
    214 
    215  GCPtr<ArgumentsObject*> mappedArgumentsTemplate;
    216  GCPtr<ArgumentsObject*> unmappedArgumentsTemplate;
    217 
    218  // Template objects to speed up allocation of Map/Set objects.
    219  GCPtr<MapObject*> mapObjectTemplate;
    220  GCPtr<SetObject*> setObjectTemplate;
    221 
    222  GCPtr<PlainObject*> iterResultTemplate;
    223  GCPtr<PlainObject*> iterResultWithoutPrototypeTemplate;
    224 
    225  // Lazily initialized script source object to use for scripts cloned from the
    226  // self-hosting stencil.
    227  GCPtr<ScriptSourceObject*> selfHostingScriptSource;
    228 
    229  // The number of times that one of the following has occurred:
    230  // 1. A property of this GlobalObject is deleted.
    231  // 2. A data property of this GlobalObject is converted to an accessor,
    232  //    or vice versa.
    233  // 3. A property is defined on the global lexical that shadows a property on
    234  //    this GlobalObject.
    235  uint32_t generationCount = 0;
    236 
    237  // Whether the |globalThis| property has been resolved on the global object.
    238  bool globalThisResolved = false;
    239 
    240  void trace(JSTracer* trc, GlobalObject* global);
    241  void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
    242                              JS::ClassInfo* info) const;
    243 
    244  static constexpr size_t offsetOfLexicalEnvironment() {
    245    static_assert(sizeof(lexicalEnvironment) == sizeof(uintptr_t),
    246                  "JIT code assumes field is pointer-sized");
    247    return offsetof(GlobalObjectData, lexicalEnvironment);
    248  }
    249  static constexpr size_t offsetOfRegExpRealm() {
    250    return offsetof(GlobalObjectData, regExpRealm);
    251  }
    252 };
    253 
    254 class GlobalObject : public NativeObject {
    255  enum : unsigned {
    256    GLOBAL_DATA_SLOT = JSCLASS_GLOBAL_APPLICATION_SLOTS,
    257 
    258    // Total reserved-slot count for global objects.
    259    RESERVED_SLOTS
    260  };
    261 
    262  // The slot count must be in the public API for JSCLASS_GLOBAL_FLAGS, and
    263  // we won't expose GlobalObject, so just assert that the two values are
    264  // synchronized.
    265  static_assert(JSCLASS_GLOBAL_SLOT_COUNT == RESERVED_SLOTS,
    266                "global object slot counts are inconsistent");
    267 
    268  // Ensure GlobalObjectData is only one dereference away.
    269  static_assert(GLOBAL_DATA_SLOT < MAX_FIXED_SLOTS,
    270                "GlobalObjectData should be stored in a fixed slot for "
    271                "performance reasons");
    272 
    273 public:
    274  using ProtoKind = GlobalObjectData::ProtoKind;
    275 
    276 private:
    277  GlobalObjectData* maybeData() {
    278    Value v = getReservedSlot(GLOBAL_DATA_SLOT);
    279    return static_cast<GlobalObjectData*>(v.toPrivate());
    280  }
    281  const GlobalObjectData* maybeData() const {
    282    Value v = getReservedSlot(GLOBAL_DATA_SLOT);
    283    return static_cast<const GlobalObjectData*>(v.toPrivate());
    284  }
    285 
    286  GlobalObjectData& data() { return *maybeData(); }
    287  const GlobalObjectData& data() const { return *maybeData(); }
    288 
    289  void initBuiltinProto(ProtoKind kind, JSObject* proto) {
    290    MOZ_ASSERT(proto);
    291    // Use set, as it's possible to construct oomTest test
    292    // cases where the proto is already initialized.
    293    //
    294    // See Bugs 1969353 and 1928852.
    295    data().builtinProtos[kind].set(proto);
    296  }
    297 
    298  void setBuiltinProto(ProtoKind kind, JSObject* proto) {
    299    MOZ_ASSERT(proto);
    300    data().builtinProtos[kind].set(proto);
    301  }
    302 
    303  bool hasBuiltinProto(ProtoKind kind) const {
    304    return bool(data().builtinProtos[kind]);
    305  }
    306  JSObject& getBuiltinProto(ProtoKind kind) const {
    307    MOZ_ASSERT(hasBuiltinProto(kind));
    308    return *data().builtinProtos[kind];
    309  }
    310 
    311 public:
    312  GlobalLexicalEnvironmentObject& lexicalEnvironment() {
    313    return *data().lexicalEnvironment;
    314  }
    315  GlobalScope& emptyGlobalScope() const;
    316 
    317  void traceData(JSTracer* trc, GlobalObject* global) {
    318    data().trace(trc, global);
    319  }
    320  void releaseData(JS::GCContext* gcx);
    321 
    322  void addSizeOfData(mozilla::MallocSizeOf mallocSizeOf,
    323                     JS::ClassInfo* info) const {
    324    if (maybeData()) {
    325      data().addSizeOfIncludingThis(mallocSizeOf, info);
    326    }
    327  }
    328 
    329  void setOriginalEval(JSFunction* evalFun) {
    330    MOZ_ASSERT(!data().eval);
    331    data().eval.init(evalFun);
    332  }
    333 
    334  bool hasConstructor(JSProtoKey key) const {
    335    return bool(data().builtinConstructors[key].constructor);
    336  }
    337  JSObject& getConstructor(JSProtoKey key) const {
    338    MOZ_ASSERT(hasConstructor(key));
    339    return *maybeGetConstructor(key);
    340  }
    341 
    342  static bool skipDeselectedConstructor(JSContext* cx, JSProtoKey key);
    343 
    344 private:
    345  enum class IfClassIsDisabled { DoNothing, Throw };
    346 
    347  static bool resolveConstructor(JSContext* cx, Handle<GlobalObject*> global,
    348                                 JSProtoKey key, IfClassIsDisabled mode);
    349 
    350 public:
    351  static bool ensureConstructor(JSContext* cx, Handle<GlobalObject*> global,
    352                                JSProtoKey key) {
    353    if (global->isStandardClassResolved(key)) {
    354      return true;
    355    }
    356    return resolveConstructor(cx, global, key, IfClassIsDisabled::Throw);
    357  }
    358 
    359  static JSObject* getOrCreateConstructor(JSContext* cx, JSProtoKey key) {
    360    MOZ_ASSERT(key != JSProto_Null);
    361    Handle<GlobalObject*> global = cx->global();
    362    if (!GlobalObject::ensureConstructor(cx, global, key)) {
    363      return nullptr;
    364    }
    365    return &global->getConstructor(key);
    366  }
    367 
    368  static JSObject* getOrCreatePrototype(JSContext* cx, JSProtoKey key) {
    369    MOZ_ASSERT(key != JSProto_Null);
    370    Handle<GlobalObject*> global = cx->global();
    371    if (!GlobalObject::ensureConstructor(cx, global, key)) {
    372      return nullptr;
    373    }
    374    return &global->getPrototype(key);
    375  }
    376 
    377  static JS::Handle<JSObject*> getOrCreatePrototypeHandle(JSContext* cx,
    378                                                          JSProtoKey key) {
    379    MOZ_ASSERT(key != JSProto_Null);
    380    Handle<GlobalObject*> global = cx->global();
    381    if (!GlobalObject::ensureConstructor(cx, global, key)) {
    382      return nullptr;
    383    }
    384    return global->getPrototypeHandle(key);
    385  }
    386 
    387  JSObject* maybeGetConstructor(JSProtoKey protoKey) const {
    388    MOZ_ASSERT(JSProto_Null < protoKey);
    389    MOZ_ASSERT(protoKey < JSProto_LIMIT);
    390    return data().builtinConstructors[protoKey].constructor;
    391  }
    392 
    393  template <typename T>
    394  T* maybeGetConstructor(JSProtoKey protoKey) const {
    395    JSObject* ctor = maybeGetConstructor(protoKey);
    396    return ctor ? &ctor->as<T>() : nullptr;
    397  }
    398 
    399  JSObject* maybeGetPrototype(JSProtoKey protoKey) const {
    400    MOZ_ASSERT(JSProto_Null < protoKey);
    401    MOZ_ASSERT(protoKey < JSProto_LIMIT);
    402    return data().builtinConstructors[protoKey].prototype;
    403  }
    404 
    405  template <typename T>
    406  T* maybeGetPrototype(JSProtoKey protoKey) const {
    407    JSObject* proto = maybeGetPrototype(protoKey);
    408    return proto ? &proto->as<T>() : nullptr;
    409  }
    410 
    411  static bool maybeResolveGlobalThis(JSContext* cx,
    412                                     Handle<GlobalObject*> global,
    413                                     bool* resolved);
    414 
    415  void setConstructor(JSProtoKey key, JSObject* obj) {
    416    MOZ_ASSERT(obj);
    417    data().builtinConstructors[key].constructor = obj;
    418  }
    419 
    420  bool hasPrototype(JSProtoKey key) const {
    421    return bool(data().builtinConstructors[key].prototype);
    422  }
    423  JSObject& getPrototype(JSProtoKey key) const {
    424    MOZ_ASSERT(hasPrototype(key));
    425    return *maybeGetPrototype(key);
    426  }
    427 
    428  JS::Handle<JSObject*> getPrototypeHandle(JSProtoKey protoKey) const {
    429    MOZ_ASSERT(hasPrototype(protoKey));
    430    MOZ_ASSERT(JSProto_Null < protoKey);
    431    MOZ_ASSERT(protoKey < JSProto_LIMIT);
    432    return Handle<JSObject*>::fromMarkedLocation(
    433        &data().builtinConstructors[protoKey].prototype.get());
    434  }
    435 
    436  void setPrototype(JSProtoKey key, JSObject* obj) {
    437    MOZ_ASSERT(obj);
    438    data().builtinConstructors[key].prototype = obj;
    439  }
    440 
    441  /*
    442   * Lazy standard classes need a way to indicate they have been initialized.
    443   * Otherwise, when we delete them, we might accidentally recreate them via
    444   * a lazy initialization. We use the presence of an object in the constructor
    445   * array to indicate that they've been initialized.
    446   *
    447   * Note: A few builtin objects, like JSON and Math, are not constructors,
    448   * so getConstructor is a bit of a misnomer.
    449   */
    450  bool isStandardClassResolved(JSProtoKey key) const {
    451    return hasConstructor(key);
    452  }
    453 
    454 private:
    455  bool classIsInitialized(JSProtoKey key) const {
    456    bool inited = hasConstructor(key);
    457    MOZ_ASSERT(inited == hasPrototype(key));
    458    return inited;
    459  }
    460 
    461  bool functionObjectClassesInitialized() const {
    462    bool inited = classIsInitialized(JSProto_Function);
    463    MOZ_ASSERT(inited == classIsInitialized(JSProto_Object));
    464    return inited;
    465  }
    466 
    467  // Disallow use of unqualified JSObject::create in GlobalObject.
    468  static GlobalObject* create(...) = delete;
    469 
    470  friend struct ::JSRuntime;
    471  static GlobalObject* createInternal(JSContext* cx, const JSClass* clasp);
    472 
    473 public:
    474  static GlobalObject* new_(JSContext* cx, const JSClass* clasp,
    475                            JSPrincipals* principals,
    476                            JS::OnNewGlobalHookOption hookOption,
    477                            const JS::RealmOptions& options);
    478 
    479  /*
    480   * Create a constructor function with the specified name and length using
    481   * ctor, a method which creates objects with the given class.
    482   */
    483  static JSFunction* createConstructor(
    484      JSContext* cx, JSNative ctor, JSAtom* name, unsigned length,
    485      gc::AllocKind kind = gc::AllocKind::FUNCTION,
    486      const JSJitInfo* jitInfo = nullptr);
    487 
    488  /*
    489   * Create an object to serve as [[Prototype]] for instances of the given
    490   * class, using |Object.prototype| as its [[Prototype]].  Users creating
    491   * prototype objects with particular internal structure (e.g. reserved
    492   * slots guaranteed to contain values of particular types) must immediately
    493   * complete the minimal initialization to make the returned object safe to
    494   * touch.
    495   */
    496  static NativeObject* createBlankPrototype(
    497      JSContext* cx, Handle<GlobalObject*> global, const JSClass* clasp,
    498      ObjectFlags objFlags = ObjectFlags());
    499 
    500  /*
    501   * Identical to createBlankPrototype, but uses proto as the [[Prototype]]
    502   * of the returned blank prototype.
    503   */
    504  static NativeObject* createBlankPrototypeInheriting(JSContext* cx,
    505                                                      const JSClass* clasp,
    506                                                      HandleObject proto);
    507 
    508  template <typename T>
    509  static T* createBlankPrototypeInheriting(JSContext* cx, HandleObject proto) {
    510    NativeObject* res = createBlankPrototypeInheriting(cx, &T::class_, proto);
    511    return res ? &res->template as<T>() : nullptr;
    512  }
    513 
    514  template <typename T>
    515  static T* createBlankPrototype(JSContext* cx, Handle<GlobalObject*> global,
    516                                 ObjectFlags objFlags = ObjectFlags()) {
    517    NativeObject* res = createBlankPrototype(cx, global, &T::class_, objFlags);
    518    return res ? &res->template as<T>() : nullptr;
    519  }
    520 
    521  // Object, Function, and eval are eagerly resolved when creating the global.
    522  JSObject& getObjectPrototype() {
    523    MOZ_ASSERT(functionObjectClassesInitialized());
    524    return getPrototype(JSProto_Object);
    525  }
    526  Handle<JSObject*> getObjectPrototypeHandle() {
    527    MOZ_ASSERT(functionObjectClassesInitialized());
    528    return getPrototypeHandle(JSProto_Object);
    529  }
    530  JSObject& getFunctionConstructor() {
    531    MOZ_ASSERT(functionObjectClassesInitialized());
    532    return getConstructor(JSProto_Function);
    533  }
    534  JSObject& getFunctionPrototype() {
    535    MOZ_ASSERT(functionObjectClassesInitialized());
    536    return getPrototype(JSProto_Function);
    537  }
    538  Handle<JSObject*> getFunctionPrototypeHandle() {
    539    MOZ_ASSERT(functionObjectClassesInitialized());
    540    return getPrototypeHandle(JSProto_Function);
    541  }
    542  JSFunction& getEvalFunction() {
    543    MOZ_ASSERT(data().eval);
    544    return *data().eval;
    545  }
    546 
    547  static NativeObject* getOrCreateArrayPrototype(JSContext* cx,
    548                                                 Handle<GlobalObject*> global) {
    549    if (!ensureConstructor(cx, global, JSProto_Array)) {
    550      return nullptr;
    551    }
    552    return &global->getPrototype(JSProto_Array).as<NativeObject>();
    553  }
    554 
    555  NativeObject* maybeGetArrayPrototype() {
    556    if (classIsInitialized(JSProto_Array)) {
    557      return &getPrototype(JSProto_Array).as<NativeObject>();
    558    }
    559    return nullptr;
    560  }
    561 
    562  static JSObject* getOrCreateBooleanPrototype(JSContext* cx,
    563                                               Handle<GlobalObject*> global) {
    564    if (!ensureConstructor(cx, global, JSProto_Boolean)) {
    565      return nullptr;
    566    }
    567    return &global->getPrototype(JSProto_Boolean);
    568  }
    569 
    570  static JSObject* getOrCreateNumberPrototype(JSContext* cx,
    571                                              Handle<GlobalObject*> global) {
    572    if (!ensureConstructor(cx, global, JSProto_Number)) {
    573      return nullptr;
    574    }
    575    return &global->getPrototype(JSProto_Number);
    576  }
    577 
    578  static JSObject* getOrCreateStringPrototype(JSContext* cx,
    579                                              Handle<GlobalObject*> global) {
    580    if (!ensureConstructor(cx, global, JSProto_String)) {
    581      return nullptr;
    582    }
    583    return &global->getPrototype(JSProto_String);
    584  }
    585 
    586  static JSObject* getOrCreateSymbolPrototype(JSContext* cx,
    587                                              Handle<GlobalObject*> global) {
    588    if (!ensureConstructor(cx, global, JSProto_Symbol)) {
    589      return nullptr;
    590    }
    591    return &global->getPrototype(JSProto_Symbol);
    592  }
    593 
    594  static JSObject* getOrCreateBigIntPrototype(JSContext* cx,
    595                                              Handle<GlobalObject*> global) {
    596    if (!ensureConstructor(cx, global, JSProto_BigInt)) {
    597      return nullptr;
    598    }
    599    return &global->getPrototype(JSProto_BigInt);
    600  }
    601 
    602  static JSObject* getOrCreatePromisePrototype(JSContext* cx,
    603                                               Handle<GlobalObject*> global) {
    604    if (!ensureConstructor(cx, global, JSProto_Promise)) {
    605      return nullptr;
    606    }
    607    return &global->getPrototype(JSProto_Promise);
    608  }
    609 
    610  static JSObject* getOrCreateRegExpPrototype(JSContext* cx,
    611                                              Handle<GlobalObject*> global) {
    612    if (!ensureConstructor(cx, global, JSProto_RegExp)) {
    613      return nullptr;
    614    }
    615    return &global->getPrototype(JSProto_RegExp);
    616  }
    617 
    618  static JSObject* getOrCreateRegExpConstructor(JSContext* cx,
    619                                                Handle<GlobalObject*> global) {
    620    if (!ensureConstructor(cx, global, JSProto_RegExp)) {
    621      return nullptr;
    622    }
    623    return &global->getConstructor(JSProto_RegExp);
    624  }
    625 
    626  JSObject* maybeGetRegExpPrototype() {
    627    if (classIsInitialized(JSProto_RegExp)) {
    628      return &getPrototype(JSProto_RegExp);
    629    }
    630    return nullptr;
    631  }
    632 
    633  static JSObject* getOrCreateSavedFramePrototype(
    634      JSContext* cx, Handle<GlobalObject*> global) {
    635    if (!ensureConstructor(cx, global, JSProto_SavedFrame)) {
    636      return nullptr;
    637    }
    638    return &global->getPrototype(JSProto_SavedFrame);
    639  }
    640 
    641  static JSObject* getOrCreateArrayBufferConstructor(
    642      JSContext* cx, Handle<GlobalObject*> global) {
    643    if (!ensureConstructor(cx, global, JSProto_ArrayBuffer)) {
    644      return nullptr;
    645    }
    646    return &global->getConstructor(JSProto_ArrayBuffer);
    647  }
    648 
    649  static JSObject* getOrCreateArrayBufferPrototype(
    650      JSContext* cx, Handle<GlobalObject*> global) {
    651    if (!ensureConstructor(cx, global, JSProto_ArrayBuffer)) {
    652      return nullptr;
    653    }
    654    return &global->getPrototype(JSProto_ArrayBuffer);
    655  }
    656 
    657  static JSObject* getOrCreateSharedArrayBufferPrototype(
    658      JSContext* cx, Handle<GlobalObject*> global) {
    659    if (!ensureConstructor(cx, global, JSProto_SharedArrayBuffer)) {
    660      return nullptr;
    661    }
    662    return &global->getPrototype(JSProto_SharedArrayBuffer);
    663  }
    664 
    665  static JSObject* getOrCreateSharedArrayBufferConstructor(
    666      JSContext* cx, Handle<GlobalObject*> global) {
    667    if (!ensureConstructor(cx, global, JSProto_SharedArrayBuffer)) {
    668      return nullptr;
    669    }
    670    return &global->getConstructor(JSProto_SharedArrayBuffer);
    671  }
    672 
    673  static JSObject* getOrCreateCustomErrorPrototype(JSContext* cx,
    674                                                   Handle<GlobalObject*> global,
    675                                                   JSExnType exnType) {
    676    JSProtoKey key = GetExceptionProtoKey(exnType);
    677    if (!ensureConstructor(cx, global, key)) {
    678      return nullptr;
    679    }
    680    return &global->getPrototype(key);
    681  }
    682 
    683  static JSFunction* getOrCreateErrorConstructor(JSContext* cx,
    684                                                 Handle<GlobalObject*> global) {
    685    if (!ensureConstructor(cx, global, JSProto_Error)) {
    686      return nullptr;
    687    }
    688    return &global->getConstructor(JSProto_Error).as<JSFunction>();
    689  }
    690 
    691  static JSObject* getOrCreateErrorPrototype(JSContext* cx,
    692                                             Handle<GlobalObject*> global) {
    693    return getOrCreateCustomErrorPrototype(cx, global, JSEXN_ERR);
    694  }
    695 
    696  static JSFunction* getOrCreateTypedArrayConstructor(
    697      JSContext* cx, Handle<GlobalObject*> global) {
    698    if (!ensureConstructor(cx, global, JSProto_TypedArray)) {
    699      return nullptr;
    700    }
    701    return &global->getConstructor(JSProto_TypedArray).as<JSFunction>();
    702  }
    703 
    704  static JSObject* getOrCreateTypedArrayPrototype(
    705      JSContext* cx, Handle<GlobalObject*> global) {
    706    if (!ensureConstructor(cx, global, JSProto_TypedArray)) {
    707      return nullptr;
    708    }
    709    return &global->getPrototype(JSProto_TypedArray);
    710  }
    711 
    712 private:
    713  using ObjectInitOp = bool (*)(JSContext*, Handle<GlobalObject*>);
    714  using ObjectInitWithTagOp = bool (*)(JSContext*, Handle<GlobalObject*>,
    715                                       Handle<JSAtom*>);
    716 
    717  static JSObject* getOrCreateBuiltinProto(JSContext* cx,
    718                                           Handle<GlobalObject*> global,
    719                                           ProtoKind kind, ObjectInitOp init) {
    720    if (JSObject* proto = global->maybeBuiltinProto(kind)) {
    721      return proto;
    722    }
    723 
    724    return createBuiltinProto(cx, global, kind, init);
    725  }
    726 
    727  static JSObject* getOrCreateBuiltinProto(JSContext* cx,
    728                                           Handle<GlobalObject*> global,
    729                                           ProtoKind kind, Handle<JSAtom*> tag,
    730                                           ObjectInitWithTagOp init) {
    731    if (JSObject* proto = global->maybeBuiltinProto(kind)) {
    732      return proto;
    733    }
    734 
    735    return createBuiltinProto(cx, global, kind, tag, init);
    736  }
    737 
    738  static JSObject* createBuiltinProto(JSContext* cx,
    739                                      Handle<GlobalObject*> global,
    740                                      ProtoKind kind, ObjectInitOp init);
    741  static JSObject* createBuiltinProto(JSContext* cx,
    742                                      Handle<GlobalObject*> global,
    743                                      ProtoKind kind, Handle<JSAtom*> tag,
    744                                      ObjectInitWithTagOp init);
    745 
    746  static JSObject* createIteratorPrototype(JSContext* cx,
    747                                           Handle<GlobalObject*> global);
    748 
    749 public:
    750  JSObject* maybeBuiltinProto(ProtoKind kind) const {
    751    return data().builtinProtos[kind];
    752  }
    753 
    754  NativeObject* maybeGetIteratorPrototype() {
    755    if (!hasPrototype(JSProto_Iterator)) {
    756      return nullptr;
    757    }
    758    return &(getPrototype(JSProto_Iterator).as<NativeObject>());
    759  }
    760 
    761  static JSObject* getOrCreateIteratorPrototype(JSContext* cx,
    762                                                Handle<GlobalObject*> global) {
    763    if (!ensureConstructor(cx, global, JSProto_Iterator)) {
    764      return nullptr;
    765    }
    766    return &global->getPrototype(JSProto_Iterator);
    767  }
    768 
    769  static NativeObject* getOrCreateArrayIteratorPrototype(
    770      JSContext* cx, Handle<GlobalObject*> global);
    771 
    772  NativeObject* maybeGetArrayIteratorPrototype() {
    773    if (JSObject* obj = maybeBuiltinProto(ProtoKind::ArrayIteratorProto)) {
    774      return &obj->as<NativeObject>();
    775    }
    776    return nullptr;
    777  }
    778 
    779  static JSObject* getOrCreateStringIteratorPrototype(
    780      JSContext* cx, Handle<GlobalObject*> global);
    781 
    782  static JSObject* getOrCreateRegExpStringIteratorPrototype(
    783      JSContext* cx, Handle<GlobalObject*> global);
    784 
    785 #ifdef NIGHTLY_BUILD
    786  static JSObject* getOrCreateIteratorRangePrototype(
    787      JSContext* cx, Handle<GlobalObject*> global);
    788 #endif
    789 
    790  void setGeneratorObjectPrototype(JSObject* obj) {
    791    setBuiltinProto(ProtoKind::GeneratorObjectProto, obj);
    792  }
    793 
    794  static JSObject* getOrCreateGeneratorObjectPrototype(
    795      JSContext* cx, Handle<GlobalObject*> global) {
    796    if (!ensureConstructor(cx, global, JSProto_GeneratorFunction)) {
    797      return nullptr;
    798    }
    799    return &global->getBuiltinProto(ProtoKind::GeneratorObjectProto);
    800  }
    801 
    802  static JSObject* getOrCreateGeneratorFunctionPrototype(
    803      JSContext* cx, Handle<GlobalObject*> global) {
    804    if (!ensureConstructor(cx, global, JSProto_GeneratorFunction)) {
    805      return nullptr;
    806    }
    807    return &global->getPrototype(JSProto_GeneratorFunction);
    808  }
    809 
    810  static JSObject* getOrCreateGeneratorFunction(JSContext* cx,
    811                                                Handle<GlobalObject*> global) {
    812    if (!ensureConstructor(cx, global, JSProto_GeneratorFunction)) {
    813      return nullptr;
    814    }
    815    return &global->getConstructor(JSProto_GeneratorFunction);
    816  }
    817 
    818  static JSObject* getOrCreateAsyncFunctionPrototype(
    819      JSContext* cx, Handle<GlobalObject*> global) {
    820    if (!ensureConstructor(cx, global, JSProto_AsyncFunction)) {
    821      return nullptr;
    822    }
    823    return &global->getPrototype(JSProto_AsyncFunction);
    824  }
    825 
    826  static JSObject* getOrCreateAsyncFunction(JSContext* cx,
    827                                            Handle<GlobalObject*> global) {
    828    if (!ensureConstructor(cx, global, JSProto_AsyncFunction)) {
    829      return nullptr;
    830    }
    831    return &global->getConstructor(JSProto_AsyncFunction);
    832  }
    833 
    834  static JSObject* createAsyncIteratorPrototype(JSContext* cx,
    835                                                Handle<GlobalObject*> global);
    836 
    837  static JSObject* getOrCreateAsyncIteratorPrototype(
    838      JSContext* cx, Handle<GlobalObject*> global) {
    839    if (JSObject* proto =
    840            global->maybeBuiltinProto(ProtoKind::AsyncIteratorProto)) {
    841      return proto;
    842    }
    843    return createAsyncIteratorPrototype(cx, global);
    844  }
    845 
    846  static JSObject* getOrCreateAsyncFromSyncIteratorPrototype(
    847      JSContext* cx, Handle<GlobalObject*> global) {
    848    return getOrCreateBuiltinProto(cx, global,
    849                                   ProtoKind::AsyncFromSyncIteratorProto,
    850                                   initAsyncFromSyncIteratorProto);
    851  }
    852 
    853  static JSObject* getOrCreateAsyncGenerator(JSContext* cx,
    854                                             Handle<GlobalObject*> global) {
    855    if (!ensureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
    856      return nullptr;
    857    }
    858    return &global->getPrototype(JSProto_AsyncGeneratorFunction);
    859  }
    860 
    861  static JSObject* getOrCreateAsyncGeneratorFunction(
    862      JSContext* cx, Handle<GlobalObject*> global) {
    863    if (!ensureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
    864      return nullptr;
    865    }
    866    return &global->getConstructor(JSProto_AsyncGeneratorFunction);
    867  }
    868 
    869  void setAsyncGeneratorPrototype(JSObject* obj) {
    870    initBuiltinProto(ProtoKind::AsyncGeneratorProto, obj);
    871  }
    872 
    873  static JSObject* getOrCreateAsyncGeneratorPrototype(
    874      JSContext* cx, Handle<GlobalObject*> global) {
    875    if (!ensureConstructor(cx, global, JSProto_AsyncGeneratorFunction)) {
    876      return nullptr;
    877    }
    878    return &global->getBuiltinProto(ProtoKind::AsyncGeneratorProto);
    879  }
    880 
    881  static JSObject* getOrCreateMapIteratorPrototype(
    882      JSContext* cx, Handle<GlobalObject*> global) {
    883    return getOrCreateBuiltinProto(cx, global, ProtoKind::MapIteratorProto,
    884                                   initMapIteratorProto);
    885  }
    886 
    887  static JSObject* getOrCreateSetIteratorPrototype(
    888      JSContext* cx, Handle<GlobalObject*> global) {
    889    return getOrCreateBuiltinProto(cx, global, ProtoKind::SetIteratorProto,
    890                                   initSetIteratorProto);
    891  }
    892 
    893  static JSObject* getOrCreateSegmentsPrototype(JSContext* cx,
    894                                                Handle<GlobalObject*> global) {
    895    return getOrCreateBuiltinProto(cx, global, ProtoKind::SegmentsProto,
    896                                   initSegmentsProto);
    897  }
    898 
    899  static JSObject* getOrCreateSegmentIteratorPrototype(
    900      JSContext* cx, Handle<GlobalObject*> global) {
    901    return getOrCreateBuiltinProto(cx, global, ProtoKind::SegmentIteratorProto,
    902                                   initSegmentIteratorProto);
    903  }
    904 
    905  static JSObject* getOrCreateDataViewPrototype(JSContext* cx,
    906                                                Handle<GlobalObject*> global) {
    907    if (!ensureConstructor(cx, global, JSProto_DataView)) {
    908      return nullptr;
    909    }
    910    return &global->getPrototype(JSProto_DataView);
    911  }
    912 
    913  static JSObject* getOrCreatePromiseConstructor(JSContext* cx,
    914                                                 Handle<GlobalObject*> global) {
    915    if (!ensureConstructor(cx, global, JSProto_Promise)) {
    916      return nullptr;
    917    }
    918    return &global->getConstructor(JSProto_Promise);
    919  }
    920 
    921  static NativeObject* getOrCreateWrapForValidIteratorPrototype(
    922      JSContext* cx, Handle<GlobalObject*> global);
    923 
    924  static NativeObject* getOrCreateIteratorHelperPrototype(
    925      JSContext* cx, Handle<GlobalObject*> global);
    926 
    927  static NativeObject* getOrCreateAsyncIteratorHelperPrototype(
    928      JSContext* cx, Handle<GlobalObject*> global);
    929  static bool initAsyncIteratorHelperProto(JSContext* cx,
    930                                           Handle<GlobalObject*> global);
    931 
    932  NativeObject& getIntrinsicsHolder() const {
    933    MOZ_ASSERT(data().intrinsicsHolder);
    934    return *data().intrinsicsHolder;
    935  }
    936 
    937  static bool createIntrinsicsHolder(JSContext* cx,
    938                                     Handle<GlobalObject*> global);
    939 
    940  NativeObject* getComputedIntrinsicsHolder() {
    941    return data().computedIntrinsicsHolder;
    942  }
    943  void setComputedIntrinsicsHolder(NativeObject* holder) {
    944    data().computedIntrinsicsHolder = holder;
    945  }
    946 
    947  // If a self-hosting intrinsic with the given |name| exists, it's stored in
    948  // |*vp| and this function returns true. Else it returns false.
    949  bool maybeGetIntrinsicValue(PropertyName* name, Value* vp, JSContext* cx) {
    950    NativeObject& holder = getIntrinsicsHolder();
    951 
    952    if (mozilla::Maybe<PropertyInfo> prop = holder.lookup(cx, name)) {
    953      *vp = holder.getSlot(prop->slot());
    954      return true;
    955    }
    956 
    957    return false;
    958  }
    959 
    960  static bool getIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
    961                                Handle<PropertyName*> name,
    962                                MutableHandleValue value) {
    963    // `undefined` in self-hosted JS code should be emitted as JSOp::Undefined.
    964    MOZ_ASSERT(name != cx->names().undefined);
    965 
    966    if (global->maybeGetIntrinsicValue(name, value.address(), cx)) {
    967      return true;
    968    }
    969    return getIntrinsicValueSlow(cx, global, name, value);
    970  }
    971 
    972  static bool getIntrinsicValueSlow(JSContext* cx, Handle<GlobalObject*> global,
    973                                    Handle<PropertyName*> name,
    974                                    MutableHandleValue value);
    975 
    976  static bool addIntrinsicValue(JSContext* cx, Handle<GlobalObject*> global,
    977                                Handle<PropertyName*> name, HandleValue value);
    978 
    979  static inline bool setIntrinsicValue(JSContext* cx,
    980                                       Handle<GlobalObject*> global,
    981                                       Handle<PropertyName*> name,
    982                                       HandleValue value);
    983 
    984  static bool getSelfHostedFunction(JSContext* cx, Handle<GlobalObject*> global,
    985                                    Handle<PropertyName*> selfHostedName,
    986                                    Handle<JSAtom*> name, unsigned nargs,
    987                                    MutableHandleValue funVal);
    988 
    989  static RegExpStatics* getRegExpStatics(JSContext* cx,
    990                                         Handle<GlobalObject*> global);
    991 
    992  static JSObject* getOrCreateThrowTypeError(JSContext* cx,
    993                                             Handle<GlobalObject*> global);
    994 
    995  RegExpRealm& regExpRealm() { return data().regExpRealm; }
    996 
    997 #ifdef JS_HAS_INTL_API
    998  intl::GlobalIntlData& globalIntlData() { return data().globalIntlData; }
    999 #endif
   1000 
   1001  // Infallibly test whether the given value is the eval function for this
   1002  // global.
   1003  bool valueIsEval(const Value& val);
   1004 
   1005  static ArgumentsObject* getOrCreateArgumentsTemplateObject(JSContext* cx,
   1006                                                             bool mapped);
   1007  ArgumentsObject* maybeArgumentsTemplateObject(bool mapped) const;
   1008 
   1009  static MapObject* getOrCreateMapTemplateObject(JSContext* cx);
   1010  static SetObject* getOrCreateSetTemplateObject(JSContext* cx);
   1011 
   1012  static const size_t IterResultObjectValueSlot = 0;
   1013  static const size_t IterResultObjectDoneSlot = 1;
   1014  static js::PlainObject* getOrCreateIterResultTemplateObject(JSContext* cx);
   1015  static js::PlainObject* getOrCreateIterResultWithoutPrototypeTemplateObject(
   1016      JSContext* cx);
   1017 
   1018 private:
   1019  enum class WithObjectPrototype { No, Yes };
   1020  static js::PlainObject* createIterResultTemplateObject(
   1021      JSContext* cx, WithObjectPrototype withProto);
   1022 
   1023 public:
   1024  static ScriptSourceObject* getOrCreateSelfHostingScriptSourceObject(
   1025      JSContext* cx, Handle<GlobalObject*> global);
   1026 
   1027  // Implemented in vm/Iteration.cpp.
   1028  template <ProtoKind Kind, const JSClass* ProtoClass,
   1029            const JSFunctionSpec* Methods, const bool needsFuseProperty = false>
   1030  static bool initObjectIteratorProto(JSContext* cx,
   1031                                      Handle<GlobalObject*> global,
   1032                                      Handle<JSAtom*> tag);
   1033 
   1034  // Implemented in vm/AsyncIteration.cpp.
   1035  static bool initAsyncIteratorProto(JSContext* cx,
   1036                                     Handle<GlobalObject*> global);
   1037  static bool initAsyncFromSyncIteratorProto(JSContext* cx,
   1038                                             Handle<GlobalObject*> global);
   1039 
   1040  // Implemented in builtin/MapObject.cpp.
   1041  static bool initMapIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
   1042  static bool initSetIteratorProto(JSContext* cx, Handle<GlobalObject*> global);
   1043 
   1044  // Implemented in builtin/intl/Segmenter.cpp.
   1045  static bool initSegmentsProto(JSContext* cx, Handle<GlobalObject*> global);
   1046  static bool initSegmentIteratorProto(JSContext* cx,
   1047                                       Handle<GlobalObject*> global);
   1048 
   1049  static bool initStandardClasses(JSContext* cx, Handle<GlobalObject*> global);
   1050 
   1051  // Disallow GC as it may mutate the vector.
   1052  Realm::DebuggerVector& getDebuggers(const JS::AutoRequireNoGC& nogc) const {
   1053    return realm()->getDebuggers(nogc);
   1054  }
   1055  bool hasDebuggers() const { return realm()->hasDebuggers(); }
   1056 
   1057  JSObject* maybeWindowProxy() const { return data().windowProxy; }
   1058 
   1059  void setWindowProxy(JSObject* windowProxy) {
   1060    // Note: the global must always be associated with the same WindowProxy.
   1061    // CacheIR optimizations rely on this by baking in the WindowProxy for the
   1062    // global.
   1063    MOZ_ASSERT(!data().windowProxy);
   1064    data().windowProxy.init(windowProxy);
   1065  }
   1066 
   1067  ArrayObject* getSourceURLsHolder() const { return data().sourceURLsHolder; }
   1068 
   1069  void setSourceURLsHolder(ArrayObject* holder) {
   1070    data().sourceURLsHolder = holder;
   1071  }
   1072  void clearSourceURLSHolder() { setSourceURLsHolder(nullptr); }
   1073 
   1074  SharedShape* maybeArrayShapeWithDefaultProto() const {
   1075    return data().arrayShapeWithDefaultProto;
   1076  }
   1077 
   1078  static SharedShape* getArrayShapeWithDefaultProto(JSContext* cx) {
   1079    if (SharedShape* shape = cx->global()->data().arrayShapeWithDefaultProto;
   1080        MOZ_LIKELY(shape)) {
   1081      return shape;
   1082    }
   1083    return createArrayShapeWithDefaultProto(cx);
   1084  }
   1085  static SharedShape* createArrayShapeWithDefaultProto(JSContext* cx);
   1086 
   1087  static SharedShape* getPlainObjectShapeWithDefaultProto(JSContext* cx,
   1088                                                          gc::AllocKind kind) {
   1089    PlainObjectSlotsKind slotsKind = PlainObjectSlotsKindFromAllocKind(kind);
   1090    SharedShape* shape =
   1091        cx->global()->data().plainObjectShapesWithDefaultProto[slotsKind];
   1092    if (MOZ_LIKELY(shape)) {
   1093      return shape;
   1094    }
   1095    return createPlainObjectShapeWithDefaultProto(cx, kind);
   1096  }
   1097  static SharedShape* createPlainObjectShapeWithDefaultProto(
   1098      JSContext* cx, gc::AllocKind kind);
   1099 
   1100  static SharedShape* getEmptyPlainObjectShape(JSContext* cx) {
   1101    const PlainObjectSlotsKind kind = PlainObjectSlotsKind::Slots0;
   1102    SharedShape* shape =
   1103        cx->global()->data().plainObjectShapesWithDefaultProto[kind];
   1104    MOZ_ASSERT(shape);  // This is created on initialization.
   1105    return shape;
   1106  }
   1107 
   1108  static SharedShape* getFunctionShapeWithDefaultProto(JSContext* cx,
   1109                                                       bool extended) {
   1110    GlobalObjectData& data = cx->global()->data();
   1111    SharedShape* shape = extended ? data.extendedFunctionShapeWithDefaultProto
   1112                                  : data.functionShapeWithDefaultProto;
   1113    if (MOZ_LIKELY(shape)) {
   1114      return shape;
   1115    }
   1116    return createFunctionShapeWithDefaultProto(cx, extended);
   1117  }
   1118  static SharedShape* createFunctionShapeWithDefaultProto(JSContext* cx,
   1119                                                          bool extended);
   1120 
   1121  SharedShape* maybeBoundFunctionShapeWithDefaultProto() const {
   1122    return data().boundFunctionShapeWithDefaultProto;
   1123  }
   1124  void setBoundFunctionShapeWithDefaultProto(SharedShape* shape) {
   1125    data().boundFunctionShapeWithDefaultProto = shape;
   1126  }
   1127 
   1128  SharedShape* maybeRegExpShapeWithDefaultProto() const {
   1129    return data().regExpShapeWithDefaultProto;
   1130  }
   1131  void setRegExpShapeWithDefaultProto(SharedShape* shape) {
   1132    data().regExpShapeWithDefaultProto = shape;
   1133  }
   1134 
   1135  static PropertyIteratorObject* getOrCreateEmptyIterator(JSContext* cx);
   1136 
   1137  // Returns an object that represents the realm, used by embedder.
   1138  static JSObject* getOrCreateRealmKeyObject(JSContext* cx,
   1139                                             Handle<GlobalObject*> global);
   1140 
   1141  static size_t offsetOfGlobalDataSlot() {
   1142    return getFixedSlotOffset(GLOBAL_DATA_SLOT);
   1143  }
   1144 
   1145  uint32_t generationCount() const { return data().generationCount; }
   1146  const void* addressOfGenerationCount() const {
   1147    return &data().generationCount;
   1148  }
   1149  void bumpGenerationCount() {
   1150    MOZ_RELEASE_ASSERT(data().generationCount < UINT32_MAX);
   1151    data().generationCount++;
   1152  }
   1153 };
   1154 
   1155 /*
   1156 * Unless otherwise specified, define ctor.prototype = proto as non-enumerable,
   1157 * non-configurable, and non-writable; and define proto.constructor = ctor as
   1158 * non-enumerable but configurable and writable.
   1159 */
   1160 extern bool LinkConstructorAndPrototype(
   1161    JSContext* cx, JSObject* ctor, JSObject* proto,
   1162    unsigned prototypeAttrs = JSPROP_PERMANENT | JSPROP_READONLY,
   1163    unsigned constructorAttrs = 0);
   1164 
   1165 /*
   1166 * Define properties and/or functions on any object. Either ps or fs, or both,
   1167 * may be null.
   1168 */
   1169 extern bool DefinePropertiesAndFunctions(JSContext* cx, HandleObject obj,
   1170                                         const JSPropertySpec* ps,
   1171                                         const JSFunctionSpec* fs);
   1172 
   1173 extern bool DefineToStringTag(JSContext* cx, HandleObject obj, JSAtom* tag);
   1174 
   1175 /*
   1176 * Convenience templates to generic constructor and prototype creation functions
   1177 * for ClassSpecs.
   1178 */
   1179 
   1180 template <JSNative ctor, unsigned length, gc::AllocKind kind,
   1181          const JSJitInfo* jitInfo = nullptr>
   1182 JSObject* GenericCreateConstructor(JSContext* cx, JSProtoKey key) {
   1183  // Note - We duplicate the trick from ClassName() so that we don't need to
   1184  // include vm/JSAtomUtils-inl.h here.
   1185  PropertyName* name = (&cx->names().Null)[key];
   1186  return GlobalObject::createConstructor(cx, ctor, name, length, kind, jitInfo);
   1187 }
   1188 
   1189 template <typename T>
   1190 JSObject* GenericCreatePrototype(JSContext* cx, JSProtoKey key) {
   1191  static_assert(
   1192      !std::is_same_v<T, PlainObject>,
   1193      "creating Object.prototype is very special and isn't handled here");
   1194  MOZ_ASSERT(&T::class_ == ProtoKeyToClass(key),
   1195             "type mismatch--probably too much copy/paste in your ClassSpec");
   1196  MOZ_ASSERT(
   1197      InheritanceProtoKeyForStandardClass(key) == JSProto_Object,
   1198      "subclasses (of anything but Object) can't use GenericCreatePrototype");
   1199  return GlobalObject::createBlankPrototype(cx, cx->global(), &T::protoClass_);
   1200 }
   1201 
   1202 // Which object(s) should be marked as having a RealmFuse property in
   1203 // GenericFinishInit.
   1204 enum class WhichHasRealmFuseProperty {
   1205  Proto,
   1206  ProtoAndCtor,
   1207 };
   1208 
   1209 template <WhichHasRealmFuseProperty FuseProperty>
   1210 inline bool GenericFinishInit(JSContext* cx, HandleObject ctor,
   1211                              HandleObject proto) {
   1212  if constexpr (FuseProperty == WhichHasRealmFuseProperty::ProtoAndCtor) {
   1213    if (!JSObject::setHasRealmFuseProperty(cx, ctor)) {
   1214      return false;
   1215    }
   1216  }
   1217  return JSObject::setHasRealmFuseProperty(cx, proto);
   1218 }
   1219 
   1220 inline JSProtoKey StandardProtoKeyOrNull(const JSObject* obj) {
   1221  return JSCLASS_CACHED_PROTO_KEY(obj->getClass());
   1222 }
   1223 
   1224 JSObject* NewTenuredObjectWithFunctionPrototype(JSContext* cx,
   1225                                                Handle<GlobalObject*> global);
   1226 
   1227 }  // namespace js
   1228 
   1229 template <>
   1230 inline bool JSObject::is<js::GlobalObject>() const {
   1231  return !!(getClass()->flags & JSCLASS_IS_GLOBAL);
   1232 }
   1233 
   1234 #endif /* vm_GlobalObject_h */