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 file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_DOMJSClass_h
8 #define mozilla_dom_DOMJSClass_h
11 #include "jsfriendapi.h"
12 #include "js/Object.h" // JS::GetClass, JS::GetReservedSlot
13 #include "js/Wrapper.h"
14 #include "mozilla/Assertions.h"
15 #include "mozilla/Attributes.h"
16 #include "mozilla/OriginTrials.h"
17 #include "mozilla/Likely.h"
19 #include "mozilla/dom/PrototypeList.h" // auto-generated
20 #include "mozilla/dom/WebIDLPrefs.h" // auto-generated
22 class nsCycleCollectionParticipant
;
24 struct JSFunctionSpec
;
25 struct JSPropertySpec
;
26 struct JSStructuredCloneReader
;
27 struct JSStructuredCloneWriter
;
28 class nsIGlobalObject
;
30 // All DOM globals must have a slot at DOM_PROTOTYPE_SLOT.
31 #define DOM_PROTOTYPE_SLOT JSCLASS_GLOBAL_SLOT_COUNT
33 // Keep this count up to date with any extra global slots added above.
34 #define DOM_GLOBAL_SLOTS 1
36 // We use these flag bits for the new bindings.
37 #define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1
38 #define JSCLASS_IS_DOMIFACEANDPROTOJSCLASS JSCLASS_USERBIT2
40 namespace mozilla::dom
{
43 * Returns true if code running in the given JSContext is allowed to access
44 * [SecureContext] API on the given JSObject.
46 * [SecureContext] API exposure is restricted to use by code in a Secure
49 * https://w3c.github.io/webappsec-secure-contexts/
51 * Since we want [SecureContext] exposure to depend on the privileges of the
52 * running code (rather than the privileges of an object's creator), this
53 * function checks to see whether the given JSContext's Realm is flagged
54 * as a Secure Context. That allows us to make sure that system principal code
55 * (which is marked as a Secure Context) can access Secure Context API on an
56 * object in a different realm, regardless of whether the other realm is a
57 * Secure Context or not.
59 * Checking the JSContext's Realm doesn't work for expanded principal
60 * globals accessing a Secure Context web page though (e.g. those used by frame
61 * scripts). To handle that we fall back to checking whether the JSObject came
62 * from a Secure Context.
64 * Note: We'd prefer this function to live in BindingUtils.h, but we need to
65 * call it in this header, and BindingUtils.h includes us (i.e. we'd have a
66 * circular dependency between headers if it lived there).
68 inline bool IsSecureContextOrObjectIsFromSecureContext(JSContext
* aCx
,
70 MOZ_ASSERT(!js::IsWrapper(aObj
));
71 return JS::GetIsSecureContext(js::GetContextRealm(aCx
)) ||
72 JS::GetIsSecureContext(js::GetNonCCWObjectRealm(aObj
));
75 typedef bool (*ResolveOwnProperty
)(
76 JSContext
* cx
, JS::Handle
<JSObject
*> wrapper
, JS::Handle
<JSObject
*> obj
,
78 JS::MutableHandle
<mozilla::Maybe
<JS::PropertyDescriptor
>> desc
);
80 typedef bool (*EnumerateOwnProperties
)(JSContext
* cx
,
81 JS::Handle
<JSObject
*> wrapper
,
82 JS::Handle
<JSObject
*> obj
,
83 JS::MutableHandleVector
<jsid
> props
);
85 typedef bool (*DeleteNamedProperty
)(JSContext
* cx
,
86 JS::Handle
<JSObject
*> wrapper
,
87 JS::Handle
<JSObject
*> obj
,
89 JS::ObjectOpResult
& opresult
);
91 // Returns true if the given global is of a type whose bit is set in
93 bool IsGlobalInExposureSet(JSContext
* aCx
, JSObject
* aGlobal
,
101 typedef bool (*PropertyEnabled
)(JSContext
* cx
, JSObject
* global
);
103 namespace GlobalNames
{
104 // The names of our possible globals. These are the names of the actual
105 // interfaces, not of the global names used to refer to them in IDL [Exposed]
107 static const uint32_t Window
= 1u << 0;
108 static const uint32_t DedicatedWorkerGlobalScope
= 1u << 1;
109 static const uint32_t SharedWorkerGlobalScope
= 1u << 2;
110 static const uint32_t ServiceWorkerGlobalScope
= 1u << 3;
111 static const uint32_t WorkerDebuggerGlobalScope
= 1u << 4;
112 static const uint32_t AudioWorkletGlobalScope
= 1u << 5;
113 static const uint32_t PaintWorkletGlobalScope
= 1u << 6;
114 static const uint32_t ShadowRealmGlobalScope
= 1u << 7;
116 static constexpr uint32_t kCount
= 8;
117 } // namespace GlobalNames
119 struct PrefableDisablers
{
120 inline bool isEnabled(JSContext
* cx
, JS::Handle
<JSObject
*> obj
) const {
121 if (nonExposedGlobals
&&
122 IsGlobalInExposureSet(cx
, JS::GetNonCCWObjectGlobal(obj
),
123 nonExposedGlobals
)) {
126 if (prefIndex
!= WebIDLPrefIndex::NoPref
&&
127 !sWebIDLPrefs
[uint16_t(prefIndex
)]()) {
130 if (secureContext
&& !IsSecureContextOrObjectIsFromSecureContext(cx
, obj
)) {
133 if (trial
!= OriginTrial(0) &&
134 !OriginTrials::IsEnabled(cx
, JS::GetNonCCWObjectGlobal(obj
), trial
)) {
135 // TODO(emilio): Perhaps reconsider the interaction between [Trial=""] and
138 // In particular, it might be desirable to only check the trial if there
139 // is no pref or the pref is disabled.
142 if (enabledFunc
&& !enabledFunc(cx
, JS::GetNonCCWObjectGlobal(obj
))) {
148 // Index into the array of StaticPrefs
149 const WebIDLPrefIndex prefIndex
;
151 // Bitmask of global names that we should not be exposed in.
152 const uint16_t nonExposedGlobals
: GlobalNames::kCount
;
154 // A boolean indicating whether a Secure Context is required.
155 const uint16_t secureContext
: 1;
157 // An origin trial controlling the feature. This can be made a bitfield too if
159 const OriginTrial trial
;
161 // A function pointer to a function that can say the property is disabled
162 // even if "enabled" is set to true. If the pointer is null the value of
163 // "enabled" is used as-is.
164 const PropertyEnabled enabledFunc
;
167 template <typename T
>
169 inline bool isEnabled(JSContext
* cx
, JS::Handle
<JSObject
*> obj
) const {
170 MOZ_ASSERT(!js::IsWrapper(obj
));
171 if (MOZ_LIKELY(!disablers
)) {
174 return disablers
->isEnabled(cx
, obj
);
177 // Things that can disable this set of specs. |nullptr| means "cannot be
179 const PrefableDisablers
* const disablers
;
181 // Array of specs, terminated in whatever way is customary for T.
182 // Null to indicate a end-of-array for Prefable, when such an
183 // indicator is needed.
184 const T
* const specs
;
193 eUnforgeableAttribute
,
198 #define NUM_BITS_PROPERTY_INFO_TYPE 3
199 #define NUM_BITS_PROPERTY_INFO_PREF_INDEX 13
200 #define NUM_BITS_PROPERTY_INFO_SPEC_INDEX 16
202 struct PropertyInfo
{
204 // MSVC generates static initializers if we store a jsid here, even if
205 // PropertyInfo has a constexpr constructor. See bug 1460341 and bug 1464036.
209 // One of PropertyType, will be used for accessing the corresponding Duo in
210 // NativePropertiesN.duos[].
211 uint32_t type
: NUM_BITS_PROPERTY_INFO_TYPE
;
212 // The index to the corresponding Preable in Duo.mPrefables[].
213 uint32_t prefIndex
: NUM_BITS_PROPERTY_INFO_PREF_INDEX
;
214 // The index to the corresponding spec in Duo.mPrefables[prefIndex].specs[].
215 uint32_t specIndex
: NUM_BITS_PROPERTY_INFO_SPEC_INDEX
;
217 void SetId(jsid aId
) {
218 static_assert(sizeof(jsid
) == sizeof(mIdBits
),
219 "jsid should fit in mIdBits");
220 mIdBits
= aId
.asRawBits();
222 MOZ_ALWAYS_INLINE jsid
Id() const { return jsid::fromRawBits(mIdBits
); }
224 bool IsStaticMethod() const { return type
== eStaticMethod
; }
226 static int Compare(const PropertyInfo
& aInfo1
, const PropertyInfo
& aInfo2
) {
227 // IdToIndexComparator needs to be updated if the order here is changed!
228 if (MOZ_UNLIKELY(aInfo1
.mIdBits
== aInfo2
.mIdBits
)) {
229 MOZ_ASSERT((aInfo1
.type
== eMethod
|| aInfo1
.type
== eStaticMethod
) &&
230 (aInfo2
.type
== eMethod
|| aInfo2
.type
== eStaticMethod
));
232 bool isStatic1
= aInfo1
.IsStaticMethod();
234 MOZ_ASSERT(isStatic1
!= aInfo2
.IsStaticMethod(),
235 "We shouldn't have 2 static methods with the same name!");
237 return isStatic1
? -1 : 1;
240 return aInfo1
.mIdBits
< aInfo2
.mIdBits
? -1 : 1;
245 ePropertyTypeCount
<= 1ull << NUM_BITS_PROPERTY_INFO_TYPE
,
246 "We have property type count that is > (1 << NUM_BITS_PROPERTY_INFO_TYPE)");
248 // Conceptually, NativeProperties has seven (Prefable<T>*, PropertyInfo*) duos
249 // (where T is one of JSFunctionSpec, JSPropertySpec, or ConstantSpec), one for
250 // each of: static methods and attributes, methods and attributes, unforgeable
251 // methods and attributes, and constants.
253 // That's 14 pointers, but in most instances most of the duos are all null, and
254 // there are many instances. To save space we use a variable-length type,
255 // NativePropertiesN<N>, to hold the data and getters to access it. It has N
256 // actual duos (stored in duos[]), plus four bits for each of the 7 possible
257 // duos: 1 bit that states if that duo is present, and 3 that state that duo's
258 // offset (if present) in duos[].
260 // All duo accesses should be done via the getters, which contain assertions
261 // that check we don't overrun the end of the struct. (The duo data members are
262 // public only so they can be statically initialized.) These assertions should
263 // never fail so long as (a) accesses to the variable-length part are guarded by
264 // appropriate Has*() calls, and (b) all instances are well-formed, i.e. the
265 // value of N matches the number of mHas* members that are true.
267 // We store all the property ids a NativePropertiesN owns in a single array of
268 // PropertyInfo structs. Each struct contains an id and the information needed
269 // to find the corresponding Prefable for the enabled check, as well as the
270 // information needed to find the correct property descriptor in the
271 // Prefable. We also store an array of indices into the PropertyInfo array,
272 // sorted by bits of the corresponding jsid. Given a jsid, this allows us to
273 // binary search for the index of the corresponding PropertyInfo, if any.
275 // Finally, we define a typedef of NativePropertiesN<7>, NativeProperties, which
276 // we use as a "base" type used to refer to all instances of NativePropertiesN.
277 // (7 is used because that's the maximum valid parameter, though any other
278 // value 1..6 could also be used.) This is reasonable because of the
279 // aforementioned assertions in the getters. Upcast() is used to convert
280 // specific instances to this "base" type.
284 // NativeProperties points to various things, and it can be hard to keep track.
285 // The following example shows the layout.
287 // Imagine an example interface, with:
289 // - 6 methods, 3 with no disablers struct, 2 sharing the same disablers
290 // struct, 1 using a different disablers struct
291 // - 4 attributes, all with no disablers
292 // - The property order is such that those using the same disablers structs are
293 // together. (This is not guaranteed, but it makes the example simpler.)
295 // Each PropertyInfo also contain indices into sMethods/sMethods_specs (for
296 // method infos) and sAttributes/sAttributes_specs (for attributes), which let
297 // them find their spec, but these are not shown.
299 // sNativeProperties sNativeProperties_ sNativeProperties_
300 // ---- sortedPropertyIndices[10] propertyInfos[10]
301 // - <several scalar fields> ---- ----
302 // - sortedPropertyIndices ----> <10 indices> +--> 0 info (method)
303 // - duos[2] ---- | 1 info (method)
304 // ----(methods) | 2 info (method)
305 // 0 - mPrefables -------> points to sMethods below | 3 info (method)
306 // - mPropertyInfos ------------------------------+ 4 info (method)
307 // 1 - mPrefables -------> points to sAttributes below 5 info (method)
308 // - mPropertyInfos ---------------------------------> 6 info (attr)
309 // ---- 7 info (attr)
310 // ---- 8 info (attr)
314 // sMethods has three entries (excluding the terminator) because there are
315 // three disablers structs. The {nullptr,nullptr} serves as the terminator.
316 // There are also END terminators within sMethod_specs; the need for these
317 // terminators (as opposed to a length) is deeply embedded in SpiderMonkey.
318 // Disablers structs are suffixed with the index of the first spec they cover.
320 // sMethods sMethods_specs
322 // 0 - nullptr +----> 0 spec
323 // - specs ----------------------+ 1 spec
324 // 1 - disablers ---> disablers4 2 spec
325 // - specs ------------------------+ 3 END
326 // 2 - disablers ---> disablers7 +--> 4 spec
327 // - specs ----------------------+ 5 spec
328 // 3 - nullptr | 6 END
329 // - nullptr +----> 7 spec
332 // sAttributes has a single entry (excluding the terminator) because all of the
333 // specs lack disablers.
335 // sAttributes sAttributes_specs
337 // 0 - nullptr +----> 0 spec
338 // - specs ----------------------+ 1 spec
339 // 1 - nullptr 2 spec
344 struct NativePropertiesN
{
345 // Duo structs are stored in the duos[] array, and each element in the array
346 // could require a different T. Therefore, we can't use the correct type for
347 // mPrefables. Instead we use void* and cast to the correct type in the
350 const /*Prefable<const T>*/ void* const mPrefables
;
351 PropertyInfo
* const mPropertyInfos
;
354 constexpr const NativePropertiesN
<7>* Upcast() const {
355 return reinterpret_cast<const NativePropertiesN
<7>*>(this);
358 const PropertyInfo
* PropertyInfos() const { return duos
[0].mPropertyInfos
; }
360 #define DO(SpecT, FieldName) \
362 /* The bitfields indicating the duo's presence and (if present) offset. */ \
363 const uint32_t mHas##FieldName##s : 1; \
364 const uint32_t m##FieldName##sOffset : 3; \
367 const Duo* FieldName##sDuo() const { \
368 MOZ_ASSERT(Has##FieldName##s()); \
369 return &duos[m##FieldName##sOffset]; \
373 bool Has##FieldName##s() const { return mHas##FieldName##s; } \
374 const Prefable<const SpecT>* FieldName##s() const { \
375 return static_cast<const Prefable<const SpecT>*>( \
376 FieldName##sDuo()->mPrefables); \
378 PropertyInfo* FieldName##PropertyInfos() const { \
379 return FieldName##sDuo()->mPropertyInfos; \
382 DO(JSFunctionSpec
, StaticMethod
)
383 DO(JSPropertySpec
, StaticAttribute
)
384 DO(JSFunctionSpec
, Method
)
385 DO(JSPropertySpec
, Attribute
)
386 DO(JSFunctionSpec
, UnforgeableMethod
)
387 DO(JSPropertySpec
, UnforgeableAttribute
)
388 DO(ConstantSpec
, Constant
)
392 // The index to the iterator method in MethodPropertyInfos() array.
393 const int16_t iteratorAliasMethodIndex
;
394 // The number of PropertyInfo structs that the duos manage. This is the total
395 // count across all duos.
396 const uint16_t propertyInfoCount
;
397 // The sorted indices array from sorting property ids, which will be used when
398 // we binary search for a property.
399 uint16_t* sortedPropertyIndices
;
404 // Ensure the struct has the expected size. The 8 is for the bitfields plus
405 // iteratorAliasMethodIndex and idsLength; the rest is for the idsSortedIndex,
407 static_assert(sizeof(NativePropertiesN
<1>) == 8 + 3 * sizeof(void*), "1 size");
408 static_assert(sizeof(NativePropertiesN
<2>) == 8 + 5 * sizeof(void*), "2 size");
409 static_assert(sizeof(NativePropertiesN
<3>) == 8 + 7 * sizeof(void*), "3 size");
410 static_assert(sizeof(NativePropertiesN
<4>) == 8 + 9 * sizeof(void*), "4 size");
411 static_assert(sizeof(NativePropertiesN
<5>) == 8 + 11 * sizeof(void*), "5 size");
412 static_assert(sizeof(NativePropertiesN
<6>) == 8 + 13 * sizeof(void*), "6 size");
413 static_assert(sizeof(NativePropertiesN
<7>) == 8 + 15 * sizeof(void*), "7 size");
416 typedef NativePropertiesN
<7> NativeProperties
;
418 struct NativePropertiesHolder
{
419 const NativeProperties
* regular
;
420 const NativeProperties
* chromeOnly
;
421 // Points to a static bool that's set to true once the regular and chromeOnly
422 // NativeProperties have been inited. This is a pointer to a bool instead of
423 // a bool value because NativePropertiesHolder is stored by value in
424 // a static const NativePropertyHooks.
428 struct NativeNamedOrIndexedPropertyHooks
{
429 // The hook to call for resolving indexed or named properties.
430 ResolveOwnProperty mResolveOwnProperty
;
431 // The hook to call for enumerating indexed or named properties.
432 EnumerateOwnProperties mEnumerateOwnProperties
;
433 // The hook to call to delete a named property. May be null if there are no
434 // named properties or no named property deleter. On success (true return)
435 // the "found" argument will be set to true if there was in fact such a named
436 // property and false otherwise. If it's set to false, the caller is expected
437 // to proceed with whatever deletion behavior it would have if there were no
438 // named properties involved at all (i.e. if the hook were null). If it's set
439 // to true, it will indicate via opresult whether the delete actually
441 DeleteNamedProperty mDeleteNamedProperty
;
444 // Helper structure for Xrays for DOM binding objects. The same instance is used
445 // for instances, interface objects and interface prototype objects of a
446 // specific interface.
447 struct NativePropertyHooks
{
448 const NativeNamedOrIndexedPropertyHooks
* mIndexedOrNamedNativeProperties
;
450 // The property arrays for this interface.
451 NativePropertiesHolder mNativeProperties
;
453 // This will be set to the ID of the interface prototype object for the
454 // interface, if it has one. If it doesn't have one it will be set to
455 // prototypes::id::_ID_Count.
456 prototypes::ID mPrototypeID
;
458 // This will be set to the ID of the interface object for the interface, if it
459 // has one. If it doesn't have one it will be set to
460 // constructors::id::_ID_Count.
461 constructors::ID mConstructorID
;
463 // The JSClass to use for expandos on our Xrays. Can be null, in which case
464 // Xrays will use a default class of their choice.
465 const JSClass
* mXrayExpandoClass
;
468 enum DOMObjectType
: uint8_t {
473 eGlobalInterfacePrototype
,
475 eNamedPropertiesObject
478 inline bool IsInstance(DOMObjectType type
) {
479 return type
== eInstance
|| type
== eGlobalInstance
;
482 inline bool IsInterfacePrototype(DOMObjectType type
) {
483 return type
== eInterfacePrototype
|| type
== eGlobalInterfacePrototype
;
486 typedef JSObject
* (*AssociatedGlobalGetter
)(JSContext
* aCx
,
487 JS::Handle
<JSObject
*> aObj
);
489 typedef JSObject
* (*ProtoGetter
)(JSContext
* aCx
);
492 * Returns a handle to the relevant WebIDL prototype object for the current
493 * compartment global (which may be a handle to null on out of memory). Once
494 * allocated, the prototype object is guaranteed to exist as long as the global
495 * does, since the global traces its array of WebIDL prototypes and
498 typedef JS::Handle
<JSObject
*> (*ProtoHandleGetter
)(JSContext
* aCx
);
501 * Serializes a WebIDL object for structured cloning. aObj may not be in the
502 * compartment of aCx in cases when we were working with a cross-compartment
503 * wrapper. aObj is expected to be an object of the DOMJSClass that we got the
506 typedef bool (*WebIDLSerializer
)(JSContext
* aCx
,
507 JSStructuredCloneWriter
* aWriter
,
508 JS::Handle
<JSObject
*> aObj
);
511 * Deserializes a WebIDL object from a structured clone serialization.
513 typedef JSObject
* (*WebIDLDeserializer
)(JSContext
* aCx
,
514 nsIGlobalObject
* aGlobal
,
515 JSStructuredCloneReader
* aReader
);
517 typedef nsWrapperCache
* (*WrapperCacheGetter
)(JS::Handle
<JSObject
*> aObj
);
519 // Special JSClass for reflected DOM objects.
521 // It would be nice to just inherit from JSClass, but that precludes pure
522 // compile-time initialization of the form |DOMJSClass = {...};|, since C++
523 // only allows brace initialization for aggregate/POD types.
526 // A list of interfaces that this object implements, in order of decreasing
528 const prototypes::ID mInterfaceChain
[MAX_PROTOTYPE_CHAIN_LENGTH
];
530 // We store the DOM object in reserved slot with index DOM_OBJECT_SLOT or in
531 // the proxy private if we use a proxy object.
532 // Sometimes it's an nsISupports and sometimes it's not; this class tells
534 const bool mDOMObjectIsISupports
;
536 const NativePropertyHooks
* mNativeHooks
;
538 // A callback to find the associated global for our C++ object. Note that
539 // this is used in cases when that global is _changing_, so it will not match
540 // the global of the JSObject* passed in to this function!
541 AssociatedGlobalGetter mGetAssociatedGlobal
;
542 ProtoHandleGetter mGetProto
;
544 // This stores the CC participant for the native, null if this class does not
545 // implement cycle collection or if it inherits from nsISupports (we can get
546 // the CC participant by QI'ing in that case).
547 nsCycleCollectionParticipant
* mParticipant
;
549 // The serializer for this class if the relevant object is [Serializable].
551 WebIDLSerializer mSerializer
;
553 // A callback to get the wrapper cache for C++ objects that don't inherit from
554 // nsISupports, or null.
555 WrapperCacheGetter mWrapperCacheGetter
;
557 static const DOMJSClass
* FromJSClass(const JSClass
* base
) {
558 MOZ_ASSERT(base
->flags
& JSCLASS_IS_DOMJSCLASS
);
559 return reinterpret_cast<const DOMJSClass
*>(base
);
562 const JSClass
* ToJSClass() const { return &mBase
; }
565 // Special JSClass for DOM interface and interface prototype objects.
566 struct DOMIfaceAndProtoJSClass
{
567 // It would be nice to just inherit from JSClass, but that precludes pure
568 // compile-time initialization of the form
569 // |DOMJSInterfaceAndPrototypeClass = {...};|, since C++ only allows brace
570 // initialization for aggregate/POD types.
573 // Either eInterface, eNamespace, eInterfacePrototype,
574 // eGlobalInterfacePrototype or eNamedPropertiesObject.
575 DOMObjectType mType
; // uint8_t
577 const prototypes::ID mPrototypeID
; // uint16_t
578 const uint32_t mDepth
;
580 const NativePropertyHooks
* mNativeHooks
;
582 ProtoGetter mGetParentProto
;
584 static const DOMIfaceAndProtoJSClass
* FromJSClass(const JSClass
* base
) {
585 MOZ_ASSERT(base
->flags
& JSCLASS_IS_DOMIFACEANDPROTOJSCLASS
);
586 return reinterpret_cast<const DOMIfaceAndProtoJSClass
*>(base
);
589 const JSClass
* ToJSClass() const { return &mBase
; }
592 // Special JSClass for DOM interface objects.
593 struct DOMIfaceJSClass
: public DOMIfaceAndProtoJSClass
{
594 // Boolean indicating whether this object wants a @@hasInstance property
595 // pointing to InterfaceHasInstance defined on it. Only ever true for the
597 bool wantsInterfaceHasInstance
;
599 // The value to return for Function.prototype.toString on this interface
601 const char* mFunToString
;
603 static const DOMIfaceJSClass
* FromJSClass(const JSClass
* base
) {
604 const DOMIfaceAndProtoJSClass
* clazz
=
605 DOMIfaceAndProtoJSClass::FromJSClass(base
);
606 MOZ_ASSERT(clazz
->mType
== eInterface
|| clazz
->mType
== eNamespace
);
607 return static_cast<const DOMIfaceJSClass
*>(clazz
);
611 class ProtoAndIfaceCache
;
613 inline bool DOMGlobalHasProtoAndIFaceCache(JSObject
* global
) {
614 MOZ_DIAGNOSTIC_ASSERT(JS::GetClass(global
)->flags
& JSCLASS_DOM_GLOBAL
);
615 // This can be undefined if we GC while creating the global
616 return !JS::GetReservedSlot(global
, DOM_PROTOTYPE_SLOT
).isUndefined();
619 inline bool HasProtoAndIfaceCache(JSObject
* global
) {
620 if (!(JS::GetClass(global
)->flags
& JSCLASS_DOM_GLOBAL
)) {
623 return DOMGlobalHasProtoAndIFaceCache(global
);
626 inline ProtoAndIfaceCache
* GetProtoAndIfaceCache(JSObject
* global
) {
627 MOZ_DIAGNOSTIC_ASSERT(JS::GetClass(global
)->flags
& JSCLASS_DOM_GLOBAL
);
628 return static_cast<ProtoAndIfaceCache
*>(
629 JS::GetReservedSlot(global
, DOM_PROTOTYPE_SLOT
).toPrivate());
632 } // namespace mozilla::dom
634 #endif /* mozilla_dom_DOMJSClass_h */