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