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/. */
7 #ifndef vm_GlobalObject_h
8 #define vm_GlobalObject_h
10 #include "js/GlobalObject.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/EnumeratedArray.h"
16 #include <type_traits>
19 #include "jsfriendapi.h"
22 #include "NamespaceImports.h"
24 #include "gc/AllocKind.h"
25 #include "js/CallArgs.h"
27 #include "js/ErrorReport.h"
28 #include "js/PropertyDescriptor.h"
29 #include "js/RootingAPI.h"
30 #include "js/TypeDecls.h"
32 #include "vm/ArrayObject.h"
33 #include "vm/JSAtomState.h"
34 #include "vm/JSContext.h"
35 #include "vm/JSFunction.h"
36 #include "vm/JSObject.h"
37 #include "vm/NativeObject.h"
39 #include "vm/RegExpShared.h"
41 #include "vm/StringType.h"
43 struct JSFunctionSpec
;
46 struct JSPropertySpec
;
49 class JS_PUBLIC_API RealmOptions
;
54 class ArgumentsObject
;
56 class GlobalLexicalEnvironmentObject
;
58 class PropertyIteratorObject
;
62 class FinalizationRegistryGlobalData
;
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
{
77 static PlainObjectSlotsKind
PlainObjectSlotsKindFromAllocKind(
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
;
95 MOZ_CRASH("Invalid kind");
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
;
104 GlobalObjectData(const GlobalObjectData
&) = delete;
105 void operator=(const GlobalObjectData
&) = delete;
108 explicit GlobalObjectData(Zone
* zone
);
112 // The global environment record's [[VarNames]] list that contains all
113 // names declared using FunctionDeclaration, GeneratorDeclaration, and
114 // VariableDeclaration declarations in global code in this global's realm.
115 // Names are only removed from this list by a |delete IdentifierReference|
116 // that successfully removes that global property.
118 GCHashSet
<HeapPtr
<JSAtom
*>, DefaultHasher
<JSAtom
*>, CellAllocPolicy
>;
119 VarNamesSet varNames
;
121 // The original values for built-in constructors (with their prototype
122 // objects) based on JSProtoKey.
124 // This is necessary to implement spec language speaking in terms of "the
125 // original Array prototype object", or "as if by the expression new Array()"
126 // referring to the original Array constructor. The actual (writable and even
127 // deletable) Object, Array, &c. properties are not stored here.
128 struct ConstructorWithProto
{
129 HeapPtr
<JSObject
*> constructor
;
130 HeapPtr
<JSObject
*> prototype
;
133 mozilla::EnumeratedArray
<JSProtoKey
, JSProto_LIMIT
, ConstructorWithProto
>;
134 CtorArray builtinConstructors
;
136 // Built-in prototypes for this global. Note that this is different from the
137 // set of built-in constructors/prototypes based on JSProtoKey.
138 enum class ProtoKind
{
142 RegExpStringIteratorProto
,
143 GeneratorObjectProto
,
145 AsyncFromSyncIteratorProto
,
149 WrapForValidIteratorProto
,
151 AsyncIteratorHelperProto
,
156 mozilla::EnumeratedArray
<ProtoKind
, ProtoKind::Limit
, HeapPtr
<JSObject
*>>;
157 ProtoArray builtinProtos
;
159 HeapPtr
<GlobalScope
*> emptyGlobalScope
;
161 // The lexical environment for global let/const/class bindings.
162 HeapPtr
<GlobalLexicalEnvironmentObject
*> lexicalEnvironment
;
164 // The WindowProxy associated with this global.
165 HeapPtr
<JSObject
*> windowProxy
;
167 // Functions and other top-level values for self-hosted code. The "computed"
168 // holder is used as the target of `SetIntrinsic` calls, but the same property
169 // may also be cached on the normal intrinsics holder for `GetIntrinsic`.
170 HeapPtr
<NativeObject
*> intrinsicsHolder
;
171 HeapPtr
<NativeObject
*> computedIntrinsicsHolder
;
173 // Cache used to optimize certain for-of operations.
174 HeapPtr
<NativeObject
*> forOfPICChain
;
176 // List of source URLs for this realm. This is used by the debugger.
177 HeapPtr
<ArrayObject
*> sourceURLsHolder
;
179 // Realm-specific object that can be used as key in WeakMaps.
180 HeapPtr
<PlainObject
*> realmKeyObject
;
182 // The unique %ThrowTypeError% function for this global.
183 HeapPtr
<JSFunction
*> throwTypeError
;
185 // The unique %eval% function (for indirect eval) for this global.
186 HeapPtr
<JSFunction
*> eval
;
188 // Empty iterator object used for for-in with null/undefined.
189 HeapPtr
<PropertyIteratorObject
*> emptyIterator
;
191 // Cached shape for new arrays with Array.prototype as prototype.
192 HeapPtr
<SharedShape
*> arrayShapeWithDefaultProto
;
194 // Shape for PlainObject with %Object.prototype% as proto, for each object
196 using PlainObjectShapeArray
= mozilla::EnumeratedArray
<
197 PlainObjectSlotsKind
, PlainObjectSlotsKind::Limit
, HeapPtr
<SharedShape
*>>;
198 PlainObjectShapeArray plainObjectShapesWithDefaultProto
;
200 // Shape for JSFunction with %Function.prototype% as proto, for both
201 // non-extended and extended functions.
202 HeapPtr
<SharedShape
*> functionShapeWithDefaultProto
;
203 HeapPtr
<SharedShape
*> extendedFunctionShapeWithDefaultProto
;
205 // Shape for BoundFunctionObject with %Function.prototype% as proto.
206 HeapPtr
<SharedShape
*> boundFunctionShapeWithDefaultProto
;
208 // Global state for regular expressions.
209 RegExpRealm regExpRealm
;
211 HeapPtr
<ArgumentsObject
*> mappedArgumentsTemplate
;
212 HeapPtr
<ArgumentsObject
*> unmappedArgumentsTemplate
;
214 HeapPtr
<PlainObject
*> iterResultTemplate
;
215 HeapPtr
<PlainObject
*> iterResultWithoutPrototypeTemplate
;
217 // Lazily initialized script source object to use for scripts cloned from the
218 // self-hosting stencil.
219 HeapPtr
<ScriptSourceObject
*> selfHostingScriptSource
;
221 UniquePtr
<gc::FinalizationRegistryGlobalData
> finalizationRegistryData
;
223 // The number of times that one of the following has occurred:
224 // 1. A property of this GlobalObject is deleted.
225 // 2. A data property of this GlobalObject is converted to an accessor,
227 // 3. A property is defined on the global lexical that shadows a property on
228 // this GlobalObject.
229 uint32_t generationCount
= 0;
231 // Whether the |globalThis| property has been resolved on the global object.
232 bool globalThisResolved
= false;
234 void trace(JSTracer
* trc
, GlobalObject
* global
);
235 void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf
,
236 JS::ClassInfo
* info
) const;
238 static constexpr size_t offsetOfLexicalEnvironment() {
239 static_assert(sizeof(lexicalEnvironment
) == sizeof(uintptr_t),
240 "JIT code assumes field is pointer-sized");
241 return offsetof(GlobalObjectData
, lexicalEnvironment
);
243 static constexpr size_t offsetOfRegExpRealm() {
244 return offsetof(GlobalObjectData
, regExpRealm
);
248 class GlobalObject
: public NativeObject
{
250 GLOBAL_DATA_SLOT
= JSCLASS_GLOBAL_APPLICATION_SLOTS
,
252 // Total reserved-slot count for global objects.
256 // The slot count must be in the public API for JSCLASS_GLOBAL_FLAGS, and
257 // we won't expose GlobalObject, so just assert that the two values are
259 static_assert(JSCLASS_GLOBAL_SLOT_COUNT
== RESERVED_SLOTS
,
260 "global object slot counts are inconsistent");
262 // Ensure GlobalObjectData is only one dereference away.
263 static_assert(GLOBAL_DATA_SLOT
< MAX_FIXED_SLOTS
,
264 "GlobalObjectData should be stored in a fixed slot for "
265 "performance reasons");
267 using ProtoKind
= GlobalObjectData::ProtoKind
;
269 GlobalObjectData
* maybeData() {
270 Value v
= getReservedSlot(GLOBAL_DATA_SLOT
);
271 return static_cast<GlobalObjectData
*>(v
.toPrivate());
273 const GlobalObjectData
* maybeData() const {
274 Value v
= getReservedSlot(GLOBAL_DATA_SLOT
);
275 return static_cast<const GlobalObjectData
*>(v
.toPrivate());
278 GlobalObjectData
& data() { return *maybeData(); }
279 const GlobalObjectData
& data() const { return *maybeData(); }
281 void initBuiltinProto(ProtoKind kind
, JSObject
* proto
) {
283 data().builtinProtos
[kind
].init(proto
);
285 bool hasBuiltinProto(ProtoKind kind
) const {
286 return bool(data().builtinProtos
[kind
]);
288 JSObject
* maybeBuiltinProto(ProtoKind kind
) const {
289 return data().builtinProtos
[kind
];
291 JSObject
& getBuiltinProto(ProtoKind kind
) const {
292 MOZ_ASSERT(hasBuiltinProto(kind
));
293 return *data().builtinProtos
[kind
];
297 GlobalLexicalEnvironmentObject
& lexicalEnvironment() {
298 return *data().lexicalEnvironment
;
300 GlobalScope
& emptyGlobalScope() const;
302 void traceData(JSTracer
* trc
, GlobalObject
* global
) {
303 data().trace(trc
, global
);
305 void releaseData(JS::GCContext
* gcx
);
307 void addSizeOfData(mozilla::MallocSizeOf mallocSizeOf
,
308 JS::ClassInfo
* info
) const {
310 data().addSizeOfIncludingThis(mallocSizeOf
, info
);
314 void setOriginalEval(JSFunction
* evalFun
) {
315 MOZ_ASSERT(!data().eval
);
316 data().eval
.init(evalFun
);
319 bool hasConstructor(JSProtoKey key
) const {
320 return bool(data().builtinConstructors
[key
].constructor
);
322 JSObject
& getConstructor(JSProtoKey key
) const {
323 MOZ_ASSERT(hasConstructor(key
));
324 return *maybeGetConstructor(key
);
327 static bool skipDeselectedConstructor(JSContext
* cx
, JSProtoKey key
);
330 enum class IfClassIsDisabled
{ DoNothing
, Throw
};
332 static bool resolveConstructor(JSContext
* cx
, Handle
<GlobalObject
*> global
,
333 JSProtoKey key
, IfClassIsDisabled mode
);
336 static bool ensureConstructor(JSContext
* cx
, Handle
<GlobalObject
*> global
,
338 if (global
->isStandardClassResolved(key
)) {
341 return resolveConstructor(cx
, global
, key
, IfClassIsDisabled::Throw
);
344 static JSObject
* getOrCreateConstructor(JSContext
* cx
, JSProtoKey key
) {
345 MOZ_ASSERT(key
!= JSProto_Null
);
346 Handle
<GlobalObject
*> global
= cx
->global();
347 if (!GlobalObject::ensureConstructor(cx
, global
, key
)) {
350 return &global
->getConstructor(key
);
353 static JSObject
* getOrCreatePrototype(JSContext
* cx
, JSProtoKey key
) {
354 MOZ_ASSERT(key
!= JSProto_Null
);
355 Handle
<GlobalObject
*> global
= cx
->global();
356 if (!GlobalObject::ensureConstructor(cx
, global
, key
)) {
359 return &global
->getPrototype(key
);
362 static JS::Handle
<JSObject
*> getOrCreatePrototypeHandle(JSContext
* cx
,
364 MOZ_ASSERT(key
!= JSProto_Null
);
365 Handle
<GlobalObject
*> global
= cx
->global();
366 if (!GlobalObject::ensureConstructor(cx
, global
, key
)) {
369 return global
->getPrototypeHandle(key
);
372 JSObject
* maybeGetConstructor(JSProtoKey protoKey
) const {
373 MOZ_ASSERT(JSProto_Null
< protoKey
);
374 MOZ_ASSERT(protoKey
< JSProto_LIMIT
);
375 return data().builtinConstructors
[protoKey
].constructor
;
378 JSObject
* maybeGetPrototype(JSProtoKey protoKey
) const {
379 MOZ_ASSERT(JSProto_Null
< protoKey
);
380 MOZ_ASSERT(protoKey
< JSProto_LIMIT
);
381 return data().builtinConstructors
[protoKey
].prototype
;
384 static bool maybeResolveGlobalThis(JSContext
* cx
,
385 Handle
<GlobalObject
*> global
,
388 void setConstructor(JSProtoKey key
, JSObject
* obj
) {
390 data().builtinConstructors
[key
].constructor
= obj
;
393 bool hasPrototype(JSProtoKey key
) const {
394 return bool(data().builtinConstructors
[key
].prototype
);
396 JSObject
& getPrototype(JSProtoKey key
) const {
397 MOZ_ASSERT(hasPrototype(key
));
398 return *maybeGetPrototype(key
);
401 JS::Handle
<JSObject
*> getPrototypeHandle(JSProtoKey protoKey
) const {
402 MOZ_ASSERT(hasPrototype(protoKey
));
403 MOZ_ASSERT(JSProto_Null
< protoKey
);
404 MOZ_ASSERT(protoKey
< JSProto_LIMIT
);
405 return Handle
<JSObject
*>::fromMarkedLocation(
406 &data().builtinConstructors
[protoKey
].prototype
.get());
409 void setPrototype(JSProtoKey key
, JSObject
* obj
) {
411 data().builtinConstructors
[key
].prototype
= obj
;
415 * Lazy standard classes need a way to indicate they have been initialized.
416 * Otherwise, when we delete them, we might accidentally recreate them via
417 * a lazy initialization. We use the presence of an object in the constructor
418 * array to indicate that they've been initialized.
420 * Note: A few builtin objects, like JSON and Math, are not constructors,
421 * so getConstructor is a bit of a misnomer.
423 bool isStandardClassResolved(JSProtoKey key
) const {
424 return hasConstructor(key
);
428 bool classIsInitialized(JSProtoKey key
) const {
429 bool inited
= hasConstructor(key
);
430 MOZ_ASSERT(inited
== hasPrototype(key
));
434 bool functionObjectClassesInitialized() const {
435 bool inited
= classIsInitialized(JSProto_Function
);
436 MOZ_ASSERT(inited
== classIsInitialized(JSProto_Object
));
440 // Disallow use of unqualified JSObject::create in GlobalObject.
441 static GlobalObject
* create(...) = delete;
443 friend struct ::JSRuntime
;
444 static GlobalObject
* createInternal(JSContext
* cx
, const JSClass
* clasp
);
447 static GlobalObject
* new_(JSContext
* cx
, const JSClass
* clasp
,
448 JSPrincipals
* principals
,
449 JS::OnNewGlobalHookOption hookOption
,
450 const JS::RealmOptions
& options
);
453 * Create a constructor function with the specified name and length using
454 * ctor, a method which creates objects with the given class.
456 static JSFunction
* createConstructor(
457 JSContext
* cx
, JSNative ctor
, JSAtom
* name
, unsigned length
,
458 gc::AllocKind kind
= gc::AllocKind::FUNCTION
,
459 const JSJitInfo
* jitInfo
= nullptr);
462 * Create an object to serve as [[Prototype]] for instances of the given
463 * class, using |Object.prototype| as its [[Prototype]]. Users creating
464 * prototype objects with particular internal structure (e.g. reserved
465 * slots guaranteed to contain values of particular types) must immediately
466 * complete the minimal initialization to make the returned object safe to
469 static NativeObject
* createBlankPrototype(
470 JSContext
* cx
, Handle
<GlobalObject
*> global
, const JSClass
* clasp
,
471 ObjectFlags objFlags
= ObjectFlags());
474 * Identical to createBlankPrototype, but uses proto as the [[Prototype]]
475 * of the returned blank prototype.
477 static NativeObject
* createBlankPrototypeInheriting(JSContext
* cx
,
478 const JSClass
* clasp
,
481 template <typename T
>
482 static T
* createBlankPrototypeInheriting(JSContext
* cx
, HandleObject proto
) {
483 NativeObject
* res
= createBlankPrototypeInheriting(cx
, &T::class_
, proto
);
484 return res
? &res
->template as
<T
>() : nullptr;
487 template <typename T
>
488 static T
* createBlankPrototype(JSContext
* cx
, Handle
<GlobalObject
*> global
,
489 ObjectFlags objFlags
= ObjectFlags()) {
490 NativeObject
* res
= createBlankPrototype(cx
, global
, &T::class_
, objFlags
);
491 return res
? &res
->template as
<T
>() : nullptr;
494 // Object, Function, and eval are eagerly resolved when creating the global.
495 JSObject
& getObjectPrototype() {
496 MOZ_ASSERT(functionObjectClassesInitialized());
497 return getPrototype(JSProto_Object
);
499 Handle
<JSObject
*> getObjectPrototypeHandle() {
500 MOZ_ASSERT(functionObjectClassesInitialized());
501 return getPrototypeHandle(JSProto_Object
);
503 JSObject
& getFunctionConstructor() {
504 MOZ_ASSERT(functionObjectClassesInitialized());
505 return getConstructor(JSProto_Function
);
507 JSObject
& getFunctionPrototype() {
508 MOZ_ASSERT(functionObjectClassesInitialized());
509 return getPrototype(JSProto_Function
);
511 JSFunction
& getEvalFunction() {
512 MOZ_ASSERT(data().eval
);
516 static NativeObject
* getOrCreateArrayPrototype(JSContext
* cx
,
517 Handle
<GlobalObject
*> global
) {
518 if (!ensureConstructor(cx
, global
, JSProto_Array
)) {
521 return &global
->getPrototype(JSProto_Array
).as
<NativeObject
>();
524 NativeObject
* maybeGetArrayPrototype() {
525 if (classIsInitialized(JSProto_Array
)) {
526 return &getPrototype(JSProto_Array
).as
<NativeObject
>();
531 static JSObject
* getOrCreateBooleanPrototype(JSContext
* cx
,
532 Handle
<GlobalObject
*> global
) {
533 if (!ensureConstructor(cx
, global
, JSProto_Boolean
)) {
536 return &global
->getPrototype(JSProto_Boolean
);
539 static JSObject
* getOrCreateNumberPrototype(JSContext
* cx
,
540 Handle
<GlobalObject
*> global
) {
541 if (!ensureConstructor(cx
, global
, JSProto_Number
)) {
544 return &global
->getPrototype(JSProto_Number
);
547 static JSObject
* getOrCreateStringPrototype(JSContext
* cx
,
548 Handle
<GlobalObject
*> global
) {
549 if (!ensureConstructor(cx
, global
, JSProto_String
)) {
552 return &global
->getPrototype(JSProto_String
);
555 static JSObject
* getOrCreateSymbolPrototype(JSContext
* cx
,
556 Handle
<GlobalObject
*> global
) {
557 if (!ensureConstructor(cx
, global
, JSProto_Symbol
)) {
560 return &global
->getPrototype(JSProto_Symbol
);
563 static JSObject
* getOrCreateBigIntPrototype(JSContext
* cx
,
564 Handle
<GlobalObject
*> global
) {
565 if (!ensureConstructor(cx
, global
, JSProto_BigInt
)) {
568 return &global
->getPrototype(JSProto_BigInt
);
571 #ifdef ENABLE_RECORD_TUPLE
572 static JSObject
* getOrCreateRecordPrototype(JSContext
* cx
,
573 Handle
<GlobalObject
*> global
) {
574 if (!ensureConstructor(cx
, global
, JSProto_Record
)) {
577 return &global
->getPrototype(JSProto_Record
);
580 static JSObject
* getOrCreateTuplePrototype(JSContext
* cx
,
581 Handle
<GlobalObject
*> global
) {
582 if (!ensureConstructor(cx
, global
, JSProto_Tuple
)) {
585 return &global
->getPrototype(JSProto_Tuple
);
589 static JSObject
* getOrCreatePromisePrototype(JSContext
* cx
,
590 Handle
<GlobalObject
*> global
) {
591 if (!ensureConstructor(cx
, global
, JSProto_Promise
)) {
594 return &global
->getPrototype(JSProto_Promise
);
597 static JSObject
* getOrCreateRegExpPrototype(JSContext
* cx
,
598 Handle
<GlobalObject
*> global
) {
599 if (!ensureConstructor(cx
, global
, JSProto_RegExp
)) {
602 return &global
->getPrototype(JSProto_RegExp
);
605 JSObject
* maybeGetRegExpPrototype() {
606 if (classIsInitialized(JSProto_RegExp
)) {
607 return &getPrototype(JSProto_RegExp
);
612 static JSObject
* getOrCreateSavedFramePrototype(
613 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
614 if (!ensureConstructor(cx
, global
, JSProto_SavedFrame
)) {
617 return &global
->getPrototype(JSProto_SavedFrame
);
620 static JSObject
* getOrCreateArrayBufferConstructor(
621 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
622 if (!ensureConstructor(cx
, global
, JSProto_ArrayBuffer
)) {
625 return &global
->getConstructor(JSProto_ArrayBuffer
);
628 static JSObject
* getOrCreateArrayBufferPrototype(
629 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
630 if (!ensureConstructor(cx
, global
, JSProto_ArrayBuffer
)) {
633 return &global
->getPrototype(JSProto_ArrayBuffer
);
636 static JSObject
* getOrCreateSharedArrayBufferPrototype(
637 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
638 if (!ensureConstructor(cx
, global
, JSProto_SharedArrayBuffer
)) {
641 return &global
->getPrototype(JSProto_SharedArrayBuffer
);
644 static JSObject
* getOrCreateCustomErrorPrototype(JSContext
* cx
,
645 Handle
<GlobalObject
*> global
,
647 JSProtoKey key
= GetExceptionProtoKey(exnType
);
648 if (!ensureConstructor(cx
, global
, key
)) {
651 return &global
->getPrototype(key
);
654 static JSFunction
* getOrCreateErrorConstructor(JSContext
* cx
,
655 Handle
<GlobalObject
*> global
) {
656 if (!ensureConstructor(cx
, global
, JSProto_Error
)) {
659 return &global
->getConstructor(JSProto_Error
).as
<JSFunction
>();
662 static JSObject
* getOrCreateErrorPrototype(JSContext
* cx
,
663 Handle
<GlobalObject
*> global
) {
664 return getOrCreateCustomErrorPrototype(cx
, global
, JSEXN_ERR
);
667 static NativeObject
* getOrCreateSetPrototype(JSContext
* cx
,
668 Handle
<GlobalObject
*> global
) {
669 if (!ensureConstructor(cx
, global
, JSProto_Set
)) {
672 return &global
->getPrototype(JSProto_Set
).as
<NativeObject
>();
675 static NativeObject
* getOrCreateWeakSetPrototype(
676 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
677 if (!ensureConstructor(cx
, global
, JSProto_WeakSet
)) {
680 return &global
->getPrototype(JSProto_WeakSet
).as
<NativeObject
>();
683 static JSFunction
* getOrCreateTypedArrayConstructor(
684 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
685 if (!ensureConstructor(cx
, global
, JSProto_TypedArray
)) {
688 return &global
->getConstructor(JSProto_TypedArray
).as
<JSFunction
>();
691 static JSObject
* getOrCreateTypedArrayPrototype(
692 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
693 if (!ensureConstructor(cx
, global
, JSProto_TypedArray
)) {
696 return &global
->getPrototype(JSProto_TypedArray
);
700 using ObjectInitOp
= bool (*)(JSContext
*, Handle
<GlobalObject
*>);
701 using ObjectInitWithTagOp
= bool (*)(JSContext
*, Handle
<GlobalObject
*>,
704 static JSObject
* getOrCreateBuiltinProto(JSContext
* cx
,
705 Handle
<GlobalObject
*> global
,
706 ProtoKind kind
, ObjectInitOp init
) {
707 if (JSObject
* proto
= global
->maybeBuiltinProto(kind
)) {
711 return createBuiltinProto(cx
, global
, kind
, init
);
714 static JSObject
* getOrCreateBuiltinProto(JSContext
* cx
,
715 Handle
<GlobalObject
*> global
,
716 ProtoKind kind
, Handle
<JSAtom
*> tag
,
717 ObjectInitWithTagOp init
) {
718 if (JSObject
* proto
= global
->maybeBuiltinProto(kind
)) {
722 return createBuiltinProto(cx
, global
, kind
, tag
, init
);
725 static JSObject
* createBuiltinProto(JSContext
* cx
,
726 Handle
<GlobalObject
*> global
,
727 ProtoKind kind
, ObjectInitOp init
);
728 static JSObject
* createBuiltinProto(JSContext
* cx
,
729 Handle
<GlobalObject
*> global
,
730 ProtoKind kind
, Handle
<JSAtom
*> tag
,
731 ObjectInitWithTagOp init
);
733 static JSObject
* createIteratorPrototype(JSContext
* cx
,
734 Handle
<GlobalObject
*> global
);
737 static JSObject
* getOrCreateIteratorPrototype(JSContext
* cx
,
738 Handle
<GlobalObject
*> global
) {
739 if (JSObject
* proto
= global
->maybeBuiltinProto(ProtoKind::IteratorProto
)) {
742 return createIteratorPrototype(cx
, global
);
745 static NativeObject
* getOrCreateArrayIteratorPrototype(
746 JSContext
* cx
, Handle
<GlobalObject
*> global
);
748 static JSObject
* getOrCreateStringIteratorPrototype(
749 JSContext
* cx
, Handle
<GlobalObject
*> global
);
751 static JSObject
* getOrCreateRegExpStringIteratorPrototype(
752 JSContext
* cx
, Handle
<GlobalObject
*> global
);
754 void setGeneratorObjectPrototype(JSObject
* obj
) {
755 initBuiltinProto(ProtoKind::GeneratorObjectProto
, obj
);
758 static JSObject
* getOrCreateGeneratorObjectPrototype(
759 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
760 if (!ensureConstructor(cx
, global
, JSProto_GeneratorFunction
)) {
763 return &global
->getBuiltinProto(ProtoKind::GeneratorObjectProto
);
766 static JSObject
* getOrCreateGeneratorFunctionPrototype(
767 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
768 if (!ensureConstructor(cx
, global
, JSProto_GeneratorFunction
)) {
771 return &global
->getPrototype(JSProto_GeneratorFunction
);
774 static JSObject
* getOrCreateGeneratorFunction(JSContext
* cx
,
775 Handle
<GlobalObject
*> global
) {
776 if (!ensureConstructor(cx
, global
, JSProto_GeneratorFunction
)) {
779 return &global
->getConstructor(JSProto_GeneratorFunction
);
782 static JSObject
* getOrCreateAsyncFunctionPrototype(
783 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
784 if (!ensureConstructor(cx
, global
, JSProto_AsyncFunction
)) {
787 return &global
->getPrototype(JSProto_AsyncFunction
);
790 static JSObject
* getOrCreateAsyncFunction(JSContext
* cx
,
791 Handle
<GlobalObject
*> global
) {
792 if (!ensureConstructor(cx
, global
, JSProto_AsyncFunction
)) {
795 return &global
->getConstructor(JSProto_AsyncFunction
);
798 static JSObject
* createAsyncIteratorPrototype(JSContext
* cx
,
799 Handle
<GlobalObject
*> global
);
801 static JSObject
* getOrCreateAsyncIteratorPrototype(
802 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
803 if (JSObject
* proto
=
804 global
->maybeBuiltinProto(ProtoKind::AsyncIteratorProto
)) {
807 return createAsyncIteratorPrototype(cx
, global
);
810 static JSObject
* getOrCreateAsyncFromSyncIteratorPrototype(
811 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
812 return getOrCreateBuiltinProto(cx
, global
,
813 ProtoKind::AsyncFromSyncIteratorProto
,
814 initAsyncFromSyncIteratorProto
);
817 static JSObject
* getOrCreateAsyncGenerator(JSContext
* cx
,
818 Handle
<GlobalObject
*> global
) {
819 if (!ensureConstructor(cx
, global
, JSProto_AsyncGeneratorFunction
)) {
822 return &global
->getPrototype(JSProto_AsyncGeneratorFunction
);
825 static JSObject
* getOrCreateAsyncGeneratorFunction(
826 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
827 if (!ensureConstructor(cx
, global
, JSProto_AsyncGeneratorFunction
)) {
830 return &global
->getConstructor(JSProto_AsyncGeneratorFunction
);
833 void setAsyncGeneratorPrototype(JSObject
* obj
) {
834 initBuiltinProto(ProtoKind::AsyncGeneratorProto
, obj
);
837 static JSObject
* getOrCreateAsyncGeneratorPrototype(
838 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
839 if (!ensureConstructor(cx
, global
, JSProto_AsyncGeneratorFunction
)) {
842 return &global
->getBuiltinProto(ProtoKind::AsyncGeneratorProto
);
845 static JSObject
* getOrCreateMapIteratorPrototype(
846 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
847 return getOrCreateBuiltinProto(cx
, global
, ProtoKind::MapIteratorProto
,
848 initMapIteratorProto
);
851 static JSObject
* getOrCreateSetIteratorPrototype(
852 JSContext
* cx
, Handle
<GlobalObject
*> global
) {
853 return getOrCreateBuiltinProto(cx
, global
, ProtoKind::SetIteratorProto
,
854 initSetIteratorProto
);
857 static JSObject
* getOrCreateDataViewPrototype(JSContext
* cx
,
858 Handle
<GlobalObject
*> global
) {
859 if (!ensureConstructor(cx
, global
, JSProto_DataView
)) {
862 return &global
->getPrototype(JSProto_DataView
);
865 static JSObject
* getOrCreatePromiseConstructor(JSContext
* cx
,
866 Handle
<GlobalObject
*> global
) {
867 if (!ensureConstructor(cx
, global
, JSProto_Promise
)) {
870 return &global
->getConstructor(JSProto_Promise
);
873 static NativeObject
* getOrCreateWrapForValidIteratorPrototype(
874 JSContext
* cx
, Handle
<GlobalObject
*> global
);
876 static NativeObject
* getOrCreateIteratorHelperPrototype(
877 JSContext
* cx
, Handle
<GlobalObject
*> global
);
879 static NativeObject
* getOrCreateAsyncIteratorHelperPrototype(
880 JSContext
* cx
, Handle
<GlobalObject
*> global
);
881 static bool initAsyncIteratorHelperProto(JSContext
* cx
,
882 Handle
<GlobalObject
*> global
);
884 NativeObject
& getIntrinsicsHolder() const {
885 MOZ_ASSERT(data().intrinsicsHolder
);
886 return *data().intrinsicsHolder
;
889 static bool createIntrinsicsHolder(JSContext
* cx
,
890 Handle
<GlobalObject
*> global
);
892 NativeObject
* getComputedIntrinsicsHolder() {
893 return data().computedIntrinsicsHolder
;
895 void setComputedIntrinsicsHolder(NativeObject
* holder
) {
896 data().computedIntrinsicsHolder
= holder
;
899 // If a self-hosting intrinsic with the given |name| exists, it's stored in
900 // |*vp| and this function returns true. Else it returns false.
901 bool maybeGetIntrinsicValue(PropertyName
* name
, Value
* vp
, JSContext
* cx
) {
902 NativeObject
& holder
= getIntrinsicsHolder();
904 if (mozilla::Maybe
<PropertyInfo
> prop
= holder
.lookup(cx
, name
)) {
905 *vp
= holder
.getSlot(prop
->slot());
912 static bool getIntrinsicValue(JSContext
* cx
, Handle
<GlobalObject
*> global
,
913 Handle
<PropertyName
*> name
,
914 MutableHandleValue value
) {
915 // `undefined` in self-hosted JS code should be emitted as JSOp::Undefined.
916 MOZ_ASSERT(name
!= cx
->names().undefined
);
918 if (global
->maybeGetIntrinsicValue(name
, value
.address(), cx
)) {
921 return getIntrinsicValueSlow(cx
, global
, name
, value
);
924 static bool getIntrinsicValueSlow(JSContext
* cx
, Handle
<GlobalObject
*> global
,
925 Handle
<PropertyName
*> name
,
926 MutableHandleValue value
);
928 static bool addIntrinsicValue(JSContext
* cx
, Handle
<GlobalObject
*> global
,
929 Handle
<PropertyName
*> name
, HandleValue value
);
931 static inline bool setIntrinsicValue(JSContext
* cx
,
932 Handle
<GlobalObject
*> global
,
933 Handle
<PropertyName
*> name
,
936 static bool getSelfHostedFunction(JSContext
* cx
, Handle
<GlobalObject
*> global
,
937 Handle
<PropertyName
*> selfHostedName
,
938 Handle
<JSAtom
*> name
, unsigned nargs
,
939 MutableHandleValue funVal
);
941 static RegExpStatics
* getRegExpStatics(JSContext
* cx
,
942 Handle
<GlobalObject
*> global
);
944 static JSObject
* getOrCreateThrowTypeError(JSContext
* cx
,
945 Handle
<GlobalObject
*> global
);
947 RegExpRealm
& regExpRealm() { return data().regExpRealm
; }
949 // Infallibly test whether the given value is the eval function for this
951 bool valueIsEval(const Value
& val
);
953 void removeFromVarNames(JSAtom
* name
) { data().varNames
.remove(name
); }
955 // Whether the given name is in [[VarNames]].
956 bool isInVarNames(JSAtom
* name
) { return data().varNames
.has(name
); }
958 // Add a name to [[VarNames]]. Reports OOM on failure.
959 [[nodiscard
]] bool addToVarNames(JSContext
* cx
, JS::Handle
<JSAtom
*> name
);
961 static ArgumentsObject
* getOrCreateArgumentsTemplateObject(JSContext
* cx
,
963 ArgumentsObject
* maybeArgumentsTemplateObject(bool mapped
) const;
965 static const size_t IterResultObjectValueSlot
= 0;
966 static const size_t IterResultObjectDoneSlot
= 1;
967 static js::PlainObject
* getOrCreateIterResultTemplateObject(JSContext
* cx
);
968 static js::PlainObject
* getOrCreateIterResultWithoutPrototypeTemplateObject(
972 enum class WithObjectPrototype
{ No
, Yes
};
973 static js::PlainObject
* createIterResultTemplateObject(
974 JSContext
* cx
, WithObjectPrototype withProto
);
977 static ScriptSourceObject
* getOrCreateSelfHostingScriptSourceObject(
978 JSContext
* cx
, Handle
<GlobalObject
*> global
);
980 // Implemented in vm/Iteration.cpp.
981 static bool initIteratorProto(JSContext
* cx
, Handle
<GlobalObject
*> global
);
982 template <ProtoKind Kind
, const JSClass
* ProtoClass
,
983 const JSFunctionSpec
* Methods
>
984 static bool initObjectIteratorProto(JSContext
* cx
,
985 Handle
<GlobalObject
*> global
,
986 Handle
<JSAtom
*> tag
);
988 // Implemented in vm/AsyncIteration.cpp.
989 static bool initAsyncIteratorProto(JSContext
* cx
,
990 Handle
<GlobalObject
*> global
);
991 static bool initAsyncFromSyncIteratorProto(JSContext
* cx
,
992 Handle
<GlobalObject
*> global
);
994 // Implemented in builtin/MapObject.cpp.
995 static bool initMapIteratorProto(JSContext
* cx
, Handle
<GlobalObject
*> global
);
996 static bool initSetIteratorProto(JSContext
* cx
, Handle
<GlobalObject
*> global
);
998 static bool initStandardClasses(JSContext
* cx
, Handle
<GlobalObject
*> global
);
1000 // Disallow GC as it may mutate the vector.
1001 Realm::DebuggerVector
& getDebuggers(const JS::AutoRequireNoGC
& nogc
) const {
1002 return realm()->getDebuggers(nogc
);
1004 bool hasDebuggers() const { return realm()->hasDebuggers(); }
1006 inline NativeObject
* getForOfPICObject() { return data().forOfPICChain
; }
1007 static NativeObject
* getOrCreateForOfPICObject(JSContext
* cx
,
1008 Handle
<GlobalObject
*> global
);
1010 JSObject
* maybeWindowProxy() const { return data().windowProxy
; }
1012 void setWindowProxy(JSObject
* windowProxy
) {
1013 // Note: the global must always be associated with the same WindowProxy.
1014 // CacheIR optimizations rely on this by baking in the WindowProxy for the
1016 MOZ_ASSERT(!data().windowProxy
);
1017 data().windowProxy
.init(windowProxy
);
1020 ArrayObject
* getSourceURLsHolder() const { return data().sourceURLsHolder
; }
1022 void setSourceURLsHolder(ArrayObject
* holder
) {
1023 data().sourceURLsHolder
= holder
;
1025 void clearSourceURLSHolder() {
1026 // This is called at the start of shrinking GCs, so avoids barriers.
1027 data().sourceURLsHolder
.unbarrieredSet(nullptr);
1030 SharedShape
* maybeArrayShapeWithDefaultProto() const {
1031 return data().arrayShapeWithDefaultProto
;
1034 static SharedShape
* getArrayShapeWithDefaultProto(JSContext
* cx
) {
1035 if (SharedShape
* shape
= cx
->global()->data().arrayShapeWithDefaultProto
;
1036 MOZ_LIKELY(shape
)) {
1039 return createArrayShapeWithDefaultProto(cx
);
1041 static SharedShape
* createArrayShapeWithDefaultProto(JSContext
* cx
);
1043 static SharedShape
* getPlainObjectShapeWithDefaultProto(JSContext
* cx
,
1044 gc::AllocKind kind
) {
1045 PlainObjectSlotsKind slotsKind
= PlainObjectSlotsKindFromAllocKind(kind
);
1046 SharedShape
* shape
=
1047 cx
->global()->data().plainObjectShapesWithDefaultProto
[slotsKind
];
1048 if (MOZ_LIKELY(shape
)) {
1051 return createPlainObjectShapeWithDefaultProto(cx
, kind
);
1053 static SharedShape
* createPlainObjectShapeWithDefaultProto(
1054 JSContext
* cx
, gc::AllocKind kind
);
1056 static SharedShape
* getFunctionShapeWithDefaultProto(JSContext
* cx
,
1058 GlobalObjectData
& data
= cx
->global()->data();
1059 SharedShape
* shape
= extended
? data
.extendedFunctionShapeWithDefaultProto
1060 : data
.functionShapeWithDefaultProto
;
1061 if (MOZ_LIKELY(shape
)) {
1064 return createFunctionShapeWithDefaultProto(cx
, extended
);
1066 static SharedShape
* createFunctionShapeWithDefaultProto(JSContext
* cx
,
1069 SharedShape
* maybeBoundFunctionShapeWithDefaultProto() const {
1070 return data().boundFunctionShapeWithDefaultProto
;
1072 void setBoundFunctionShapeWithDefaultProto(SharedShape
* shape
) {
1073 data().boundFunctionShapeWithDefaultProto
= shape
;
1076 static PropertyIteratorObject
* getOrCreateEmptyIterator(JSContext
* cx
);
1078 // Returns an object that represents the realm, used by embedder.
1079 static JSObject
* getOrCreateRealmKeyObject(JSContext
* cx
,
1080 Handle
<GlobalObject
*> global
);
1082 gc::FinalizationRegistryGlobalData
* getOrCreateFinalizationRegistryData();
1083 gc::FinalizationRegistryGlobalData
* maybeFinalizationRegistryData() const {
1084 return data().finalizationRegistryData
.get();
1087 static size_t offsetOfGlobalDataSlot() {
1088 return getFixedSlotOffset(GLOBAL_DATA_SLOT
);
1091 uint32_t generationCount() const { return data().generationCount
; }
1092 const void* addressOfGenerationCount() const {
1093 return &data().generationCount
;
1095 void bumpGenerationCount() {
1096 MOZ_RELEASE_ASSERT(data().generationCount
< UINT32_MAX
);
1097 data().generationCount
++;
1102 * Unless otherwise specified, define ctor.prototype = proto as non-enumerable,
1103 * non-configurable, and non-writable; and define proto.constructor = ctor as
1104 * non-enumerable but configurable and writable.
1106 extern bool LinkConstructorAndPrototype(
1107 JSContext
* cx
, JSObject
* ctor
, JSObject
* proto
,
1108 unsigned prototypeAttrs
= JSPROP_PERMANENT
| JSPROP_READONLY
,
1109 unsigned constructorAttrs
= 0);
1112 * Define properties and/or functions on any object. Either ps or fs, or both,
1115 extern bool DefinePropertiesAndFunctions(JSContext
* cx
, HandleObject obj
,
1116 const JSPropertySpec
* ps
,
1117 const JSFunctionSpec
* fs
);
1119 extern bool DefineToStringTag(JSContext
* cx
, HandleObject obj
, JSAtom
* tag
);
1122 * Convenience templates to generic constructor and prototype creation functions
1126 template <JSNative ctor
, unsigned length
, gc::AllocKind kind
,
1127 const JSJitInfo
* jitInfo
= nullptr>
1128 JSObject
* GenericCreateConstructor(JSContext
* cx
, JSProtoKey key
) {
1129 // Note - We duplicate the trick from ClassName() so that we don't need to
1130 // include vm/JSAtomUtils-inl.h here.
1131 PropertyName
* name
= (&cx
->names().Null
)[key
];
1132 return GlobalObject::createConstructor(cx
, ctor
, name
, length
, kind
, jitInfo
);
1135 template <typename T
>
1136 JSObject
* GenericCreatePrototype(JSContext
* cx
, JSProtoKey key
) {
1138 !std::is_same_v
<T
, PlainObject
>,
1139 "creating Object.prototype is very special and isn't handled here");
1140 MOZ_ASSERT(&T::class_
== ProtoKeyToClass(key
),
1141 "type mismatch--probably too much copy/paste in your ClassSpec");
1143 InheritanceProtoKeyForStandardClass(key
) == JSProto_Object
,
1144 "subclasses (of anything but Object) can't use GenericCreatePrototype");
1145 return GlobalObject::createBlankPrototype(cx
, cx
->global(), &T::protoClass_
);
1148 inline JSProtoKey
StandardProtoKeyOrNull(const JSObject
* obj
) {
1149 return JSCLASS_CACHED_PROTO_KEY(obj
->getClass());
1152 JSObject
* NewTenuredObjectWithFunctionPrototype(JSContext
* cx
,
1153 Handle
<GlobalObject
*> global
);
1158 inline bool JSObject::is
<js::GlobalObject
>() const {
1159 return !!(getClass()->flags
& JSCLASS_IS_GLOBAL
);
1162 #endif /* vm_GlobalObject_h */