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