LCOV - code coverage report
Current view: top level - dom/bindings - DOMJSClass.h (source / functions) Hit Total Coverage
Test: output.info Lines: 20 43 46.5 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : #ifndef mozilla_dom_DOMJSClass_h
       8             : #define mozilla_dom_DOMJSClass_h
       9             : 
      10             : #include "jsfriendapi.h"
      11             : #include "js/Wrapper.h"
      12             : #include "mozilla/Assertions.h"
      13             : #include "mozilla/Attributes.h"
      14             : #include "mozilla/Likely.h"
      15             : 
      16             : #include "mozilla/dom/PrototypeList.h" // auto-generated
      17             : 
      18             : #include "mozilla/dom/JSSlots.h"
      19             : 
      20             : class nsCycleCollectionParticipant;
      21             : 
      22             : // All DOM globals must have a slot at DOM_PROTOTYPE_SLOT.
      23             : #define DOM_PROTOTYPE_SLOT JSCLASS_GLOBAL_SLOT_COUNT
      24             : 
      25             : // Keep this count up to date with any extra global slots added above.
      26             : #define DOM_GLOBAL_SLOTS 1
      27             : 
      28             : // We use these flag bits for the new bindings.
      29             : #define JSCLASS_DOM_GLOBAL JSCLASS_USERBIT1
      30             : #define JSCLASS_IS_DOMIFACEANDPROTOJSCLASS JSCLASS_USERBIT2
      31             : 
      32             : namespace mozilla {
      33             : namespace dom {
      34             : 
      35             : /**
      36             :  * Returns true if code running in the given JSContext is allowed to access
      37             :  * [SecureContext] API on the given JSObject.
      38             :  *
      39             :  * [SecureContext] API exposure is restricted to use by code in a Secure
      40             :  * Contexts:
      41             :  *
      42             :  *   https://w3c.github.io/webappsec-secure-contexts/
      43             :  *
      44             :  * Since we want [SecureContext] exposure to depend on the privileges of the
      45             :  * running code (rather than the privileges of an object's creator), this
      46             :  * function checks to see whether the given JSContext's Realm is flagged
      47             :  * as a Secure Context.  That allows us to make sure that system principal code
      48             :  * (which is marked as a Secure Context) can access Secure Context API on an
      49             :  * object in a different realm, regardless of whether the other realm is a
      50             :  * Secure Context or not.
      51             :  *
      52             :  * Checking the JSContext's Realm doesn't work for expanded principal
      53             :  * globals accessing a Secure Context web page though (e.g. those used by frame
      54             :  * scripts).  To handle that we fall back to checking whether the JSObject came
      55             :  * from a Secure Context.
      56             :  *
      57             :  * Note: We'd prefer this function to live in BindingUtils.h, but we need to
      58             :  * call it in this header, and BindingUtils.h includes us (i.e. we'd have a
      59             :  * circular dependency between headers if it lived there).
      60             :  */
      61             : inline bool
      62           0 : IsSecureContextOrObjectIsFromSecureContext(JSContext* aCx, JSObject* aObj)
      63             : {
      64           0 :   MOZ_ASSERT(!js::IsWrapper(aObj));
      65           0 :   return JS::GetIsSecureContext(js::GetContextRealm(aCx)) ||
      66          42 :          JS::GetIsSecureContext(js::GetNonCCWObjectRealm(aObj));
      67             : }
      68             : 
      69             : typedef bool
      70             : (* ResolveOwnProperty)(JSContext* cx, JS::Handle<JSObject*> wrapper,
      71             :                        JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
      72             :                        JS::MutableHandle<JS::PropertyDescriptor> desc);
      73             : 
      74             : typedef bool
      75             : (* EnumerateOwnProperties)(JSContext* cx, JS::Handle<JSObject*> wrapper,
      76             :                            JS::Handle<JSObject*> obj,
      77             :                            JS::AutoIdVector& props);
      78             : 
      79             : typedef bool
      80             : (* DeleteNamedProperty)(JSContext* cx, JS::Handle<JSObject*> wrapper,
      81             :                         JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
      82             :                         JS::ObjectOpResult& opresult);
      83             : 
      84             : // Returns true if the given global is of a type whose bit is set in
      85             : // aNonExposedGlobals.
      86             : bool
      87             : IsNonExposedGlobal(JSContext* aCx, JSObject* aGlobal,
      88             :                    uint32_t aNonExposedGlobals);
      89             : 
      90             : struct ConstantSpec
      91             : {
      92             :   const char* name;
      93             :   JS::Value value;
      94             : };
      95             : 
      96             : typedef bool (*PropertyEnabled)(JSContext* cx, JSObject* global);
      97             : 
      98             : namespace GlobalNames {
      99             : // The names of our possible globals.  These are the names of the actual
     100             : // interfaces, not of the global names used to refer to them in IDL [Exposed]
     101             : // annotations.
     102             : static const uint32_t Window = 1u << 0;
     103             : static const uint32_t BackstagePass = 1u << 1;
     104             : static const uint32_t DedicatedWorkerGlobalScope = 1u << 2;
     105             : static const uint32_t SharedWorkerGlobalScope = 1u << 3;
     106             : static const uint32_t ServiceWorkerGlobalScope = 1u << 4;
     107             : static const uint32_t WorkerDebuggerGlobalScope = 1u << 5;
     108             : static const uint32_t WorkletGlobalScope = 1u << 6;
     109             : } // namespace GlobalNames
     110             : 
     111             : struct PrefableDisablers {
     112         954 :   inline bool isEnabled(JSContext* cx, JS::Handle<JSObject*> obj) const {
     113             :     // Reading "enabled" on a worker thread is technically undefined behavior,
     114             :     // because it's written only on main threads, with no barriers of any sort.
     115             :     // So we want to avoid doing that.  But we don't particularly want to make
     116             :     // expensive NS_IsMainThread calls here.
     117             :     //
     118             :     // The good news is that "enabled" is only written for things that have a
     119             :     // Pref annotation, and such things can never be exposed on non-Window
     120             :     // globals; our IDL parser enforces that.  So as long as we check our
     121             :     // exposure set before checking "enabled" we will be ok.
     122           0 :     if (nonExposedGlobals &&
     123         290 :         IsNonExposedGlobal(cx, js::GetGlobalForObjectCrossCompartment(obj),
     124             :                            nonExposedGlobals)) {
     125             :       return false;
     126             :     }
     127         906 :     if (!enabled) {
     128             :       return false;
     129             :     }
     130         838 :     if (secureContext && !IsSecureContextOrObjectIsFromSecureContext(cx, obj)) {
     131             :       return false;
     132             :     }
     133           0 :     if (enabledFunc &&
     134        1042 :         !enabledFunc(cx, js::GetGlobalForObjectCrossCompartment(obj))) {
     135             :       return false;
     136             :     }
     137         648 :     return true;
     138             :   }
     139             : 
     140             :   // A boolean indicating whether this set of specs is enabled. Not const
     141             :   // because it will change at runtime if the corresponding pref is changed.
     142             :   bool enabled;
     143             : 
     144             :   // A boolean indicating whether a Secure Context is required.
     145             :   const bool secureContext;
     146             : 
     147             :   // Bitmask of global names that we should not be exposed in.
     148             :   const uint16_t nonExposedGlobals;
     149             : 
     150             :   // A function pointer to a function that can say the property is disabled
     151             :   // even if "enabled" is set to true.  If the pointer is null the value of
     152             :   // "enabled" is used as-is.
     153             :   const PropertyEnabled enabledFunc;
     154             : };
     155             : 
     156             : template<typename T>
     157             : struct Prefable {
     158           0 :   inline bool isEnabled(JSContext* cx, JS::Handle<JSObject*> obj) const {
     159           0 :     MOZ_ASSERT(!js::IsWrapper(obj));
     160        2729 :     if (MOZ_LIKELY(!disablers)) {
     161             :       return true;
     162             :     }
     163         954 :     return disablers->isEnabled(cx, obj);
     164             :   }
     165             : 
     166             :   // Things that can disable this set of specs. |nullptr| means "cannot be
     167             :   // disabled".
     168             :   PrefableDisablers* const disablers;
     169             : 
     170             :   // Array of specs, terminated in whatever way is customary for T.
     171             :   // Null to indicate a end-of-array for Prefable, when such an
     172             :   // indicator is needed.
     173             :   const T* const specs;
     174             : };
     175             : 
     176             : enum PropertyType {
     177             :   eStaticMethod,
     178             :   eStaticAttribute,
     179             :   eMethod,
     180             :   eAttribute,
     181             :   eUnforgeableMethod,
     182             :   eUnforgeableAttribute,
     183             :   eConstant,
     184             :   ePropertyTypeCount
     185             : };
     186             : 
     187             : #define NUM_BITS_PROPERTY_INFO_TYPE        3
     188             : #define NUM_BITS_PROPERTY_INFO_PREF_INDEX 13
     189             : #define NUM_BITS_PROPERTY_INFO_SPEC_INDEX 16
     190             : 
     191             : struct PropertyInfo {
     192             : private:
     193             :   // MSVC generates static initializers if we store a jsid here, even if
     194             :   // PropertyInfo has a constexpr constructor. See bug 1460341 and bug 1464036.
     195             :   uintptr_t mIdBits;
     196             : public:
     197             :   // One of PropertyType, will be used for accessing the corresponding Duo in
     198             :   // NativePropertiesN.duos[].
     199             :   uint32_t type: NUM_BITS_PROPERTY_INFO_TYPE;
     200             :   // The index to the corresponding Preable in Duo.mPrefables[].
     201             :   uint32_t prefIndex: NUM_BITS_PROPERTY_INFO_PREF_INDEX;
     202             :   // The index to the corresponding spec in Duo.mPrefables[prefIndex].specs[].
     203             :   uint32_t specIndex: NUM_BITS_PROPERTY_INFO_SPEC_INDEX;
     204             : 
     205             :   void SetId(jsid aId) {
     206             :     static_assert(sizeof(jsid) == sizeof(mIdBits), "jsid should fit in mIdBits");
     207        2833 :     mIdBits = JSID_BITS(aId);
     208             :   }
     209             :   MOZ_ALWAYS_INLINE jsid Id() const {
     210      153884 :     return jsid::fromRawBits(mIdBits);
     211             :   }
     212             : };
     213             : 
     214             : static_assert(ePropertyTypeCount <= 1ull << NUM_BITS_PROPERTY_INFO_TYPE,
     215             :     "We have property type count that is > (1 << NUM_BITS_PROPERTY_INFO_TYPE)");
     216             : 
     217             : // Conceptually, NativeProperties has seven (Prefable<T>*, PropertyInfo*) duos
     218             : // (where T is one of JSFunctionSpec, JSPropertySpec, or ConstantSpec), one for
     219             : // each of: static methods and attributes, methods and attributes, unforgeable
     220             : // methods and attributes, and constants.
     221             : //
     222             : // That's 14 pointers, but in most instances most of the duos are all null, and
     223             : // there are many instances. To save space we use a variable-length type,
     224             : // NativePropertiesN<N>, to hold the data and getters to access it. It has N
     225             : // actual duos (stored in duos[]), plus four bits for each of the 7 possible
     226             : // duos: 1 bit that states if that duo is present, and 3 that state that duo's
     227             : // offset (if present) in duos[].
     228             : //
     229             : // All duo accesses should be done via the getters, which contain assertions
     230             : // that check we don't overrun the end of the struct. (The duo data members are
     231             : // public only so they can be statically initialized.) These assertions should
     232             : // never fail so long as (a) accesses to the variable-length part are guarded by
     233             : // appropriate Has*() calls, and (b) all instances are well-formed, i.e. the
     234             : // value of N matches the number of mHas* members that are true.
     235             : //
     236             : // We store all the property ids a NativePropertiesN owns in a single array of
     237             : // PropertyInfo structs. Each struct contains an id and the information needed
     238             : // to find the corresponding Prefable for the enabled check, as well as the
     239             : // information needed to find the correct property descriptor in the
     240             : // Prefable. We also store an array of indices into the PropertyInfo array,
     241             : // sorted by bits of the corresponding jsid. Given a jsid, this allows us to
     242             : // binary search for the index of the corresponding PropertyInfo, if any.
     243             : //
     244             : // Finally, we define a typedef of NativePropertiesN<7>, NativeProperties, which
     245             : // we use as a "base" type used to refer to all instances of NativePropertiesN.
     246             : // (7 is used because that's the maximum valid parameter, though any other
     247             : // value 1..6 could also be used.) This is reasonable because of the
     248             : // aforementioned assertions in the getters. Upcast() is used to convert
     249             : // specific instances to this "base" type.
     250             : //
     251             : template <int N>
     252             : struct NativePropertiesN {
     253             :   // Duo structs are stored in the duos[] array, and each element in the array
     254             :   // could require a different T. Therefore, we can't use the correct type for
     255             :   // mPrefables. Instead we use void* and cast to the correct type in the
     256             :   // getters.
     257             :   struct Duo {
     258             :     const /*Prefable<const T>*/ void* const mPrefables;
     259             :     PropertyInfo* const mPropertyInfos;
     260             :   };
     261             : 
     262             :   constexpr const NativePropertiesN<7>* Upcast() const {
     263             :     return reinterpret_cast<const NativePropertiesN<7>*>(this);
     264             :   }
     265             : 
     266             :   const PropertyInfo* PropertyInfos() const {
     267             :     return duos[0].mPropertyInfos;
     268             :   }
     269             : 
     270             : #define DO(SpecT, FieldName) \
     271             : public: \
     272             :   /* The bitfields indicating the duo's presence and (if present) offset. */ \
     273             :   const uint32_t mHas##FieldName##s:1; \
     274             :   const uint32_t m##FieldName##sOffset:3; \
     275             : private: \
     276             :   const Duo* FieldName##sDuo() const { \
     277             :     MOZ_ASSERT(Has##FieldName##s()); \
     278             :     return &duos[m##FieldName##sOffset]; \
     279             :   } \
     280             : public: \
     281             :   bool Has##FieldName##s() const { \
     282             :     return mHas##FieldName##s; \
     283             :   } \
     284             :   const Prefable<const SpecT>* FieldName##s() const { \
     285             :     return static_cast<const Prefable<const SpecT>*> \
     286             :                       (FieldName##sDuo()->mPrefables); \
     287             :   } \
     288             :   PropertyInfo* FieldName##PropertyInfos() const { \
     289             :     return FieldName##sDuo()->mPropertyInfos; \
     290             :   }
     291             : 
     292           0 :   DO(JSFunctionSpec, StaticMethod)
     293           0 :   DO(JSPropertySpec, StaticAttribute)
     294           0 :   DO(JSFunctionSpec, Method)
     295           0 :   DO(JSPropertySpec, Attribute)
     296           0 :   DO(JSFunctionSpec, UnforgeableMethod)
     297           0 :   DO(JSPropertySpec, UnforgeableAttribute)
     298        1692 :   DO(ConstantSpec,   Constant)
     299             : 
     300             : #undef DO
     301             : 
     302             :   // The index to the iterator method in MethodPropertyInfos() array.
     303             :   const int16_t iteratorAliasMethodIndex;
     304             :   // The number of PropertyInfo structs that the duos manage. This is the total
     305             :   // count across all duos.
     306             :   const uint16_t propertyInfoCount;
     307             :   // The sorted indices array from sorting property ids, which will be used when
     308             :   // we binary search for a property.
     309             :   uint16_t* sortedPropertyIndices;
     310             : 
     311             :   const Duo duos[N];
     312             : };
     313             : 
     314             : // Ensure the struct has the expected size. The 8 is for the bitfields plus
     315             : // iteratorAliasMethodIndex and idsLength; the rest is for the idsSortedIndex,
     316             : // and duos[].
     317             : static_assert(sizeof(NativePropertiesN<1>) == 8 +  3*sizeof(void*), "1 size");
     318             : static_assert(sizeof(NativePropertiesN<2>) == 8 +  5*sizeof(void*), "2 size");
     319             : static_assert(sizeof(NativePropertiesN<3>) == 8 +  7*sizeof(void*), "3 size");
     320             : static_assert(sizeof(NativePropertiesN<4>) == 8 +  9*sizeof(void*), "4 size");
     321             : static_assert(sizeof(NativePropertiesN<5>) == 8 + 11*sizeof(void*), "5 size");
     322             : static_assert(sizeof(NativePropertiesN<6>) == 8 + 13*sizeof(void*), "6 size");
     323             : static_assert(sizeof(NativePropertiesN<7>) == 8 + 15*sizeof(void*), "7 size");
     324             : 
     325             : // The "base" type.
     326             : typedef NativePropertiesN<7> NativeProperties;
     327             : 
     328             : struct NativePropertiesHolder
     329             : {
     330             :   const NativeProperties* regular;
     331             :   const NativeProperties* chromeOnly;
     332             : };
     333             : 
     334             : // Helper structure for Xrays for DOM binding objects. The same instance is used
     335             : // for instances, interface objects and interface prototype objects of a
     336             : // specific interface.
     337             : struct NativePropertyHooks
     338             : {
     339             :   // The hook to call for resolving indexed or named properties. May be null if
     340             :   // there can't be any.
     341             :   ResolveOwnProperty mResolveOwnProperty;
     342             :   // The hook to call for enumerating indexed or named properties. May be null
     343             :   // if there can't be any.
     344             :   EnumerateOwnProperties mEnumerateOwnProperties;
     345             :   // The hook to call to delete a named property.  May be null if there are no
     346             :   // named properties or no named property deleter.  On success (true return)
     347             :   // the "found" argument will be set to true if there was in fact such a named
     348             :   // property and false otherwise.  If it's set to false, the caller is expected
     349             :   // to proceed with whatever deletion behavior it would have if there were no
     350             :   // named properties involved at all (i.e. if the hook were null).  If it's set
     351             :   // to true, it will indicate via opresult whether the delete actually
     352             :   // succeeded.
     353             :   DeleteNamedProperty mDeleteNamedProperty;
     354             : 
     355             :   // The property arrays for this interface.
     356             :   NativePropertiesHolder mNativeProperties;
     357             : 
     358             :   // This will be set to the ID of the interface prototype object for the
     359             :   // interface, if it has one. If it doesn't have one it will be set to
     360             :   // prototypes::id::_ID_Count.
     361             :   prototypes::ID mPrototypeID;
     362             : 
     363             :   // This will be set to the ID of the interface object for the interface, if it
     364             :   // has one. If it doesn't have one it will be set to
     365             :   // constructors::id::_ID_Count.
     366             :   constructors::ID mConstructorID;
     367             : 
     368             :   // The NativePropertyHooks instance for the parent interface (for
     369             :   // ShimInterfaceInfo).
     370             :   const NativePropertyHooks* mProtoHooks;
     371             : 
     372             :   // The JSClass to use for expandos on our Xrays.  Can be null, in which case
     373             :   // Xrays will use a default class of their choice.
     374             :   const JSClass* mXrayExpandoClass;
     375             : };
     376             : 
     377             : enum DOMObjectType : uint8_t {
     378             :   eInstance,
     379             :   eGlobalInstance,
     380             :   eInterface,
     381             :   eInterfacePrototype,
     382             :   eGlobalInterfacePrototype,
     383             :   eNamedPropertiesObject
     384             : };
     385             : 
     386             : inline
     387             : bool
     388             : IsInstance(DOMObjectType type)
     389             : {
     390             :   return type == eInstance || type == eGlobalInstance;
     391             : }
     392             : 
     393             : inline
     394             : bool
     395             : IsInterfacePrototype(DOMObjectType type)
     396             : {
     397         148 :   return type == eInterfacePrototype || type == eGlobalInterfacePrototype;
     398             : }
     399             : 
     400             : typedef JSObject* (*AssociatedGlobalGetter)(JSContext* aCx,
     401             :                                             JS::Handle<JSObject*> aObj);
     402             : 
     403             : typedef JSObject* (*ProtoGetter)(JSContext* aCx);
     404             : 
     405             : /**
     406             :  * Returns a handle to the relevant WebIDL prototype object for the current
     407             :  * compartment global (which may be a handle to null on out of memory).  Once
     408             :  * allocated, the prototype object is guaranteed to exist as long as the global
     409             :  * does, since the global traces its array of WebIDL prototypes and
     410             :  * constructors.
     411             :  */
     412             : typedef JS::Handle<JSObject*> (*ProtoHandleGetter)(JSContext* aCx);
     413             : 
     414             : // Special JSClass for reflected DOM objects.
     415             : struct DOMJSClass
     416             : {
     417             :   // It would be nice to just inherit from JSClass, but that precludes pure
     418             :   // compile-time initialization of the form |DOMJSClass = {...};|, since C++
     419             :   // only allows brace initialization for aggregate/POD types.
     420             :   const js::Class mBase;
     421             : 
     422             :   // A list of interfaces that this object implements, in order of decreasing
     423             :   // derivedness.
     424             :   const prototypes::ID mInterfaceChain[MAX_PROTOTYPE_CHAIN_LENGTH];
     425             : 
     426             :   // We store the DOM object in reserved slot with index DOM_OBJECT_SLOT or in
     427             :   // the proxy private if we use a proxy object.
     428             :   // Sometimes it's an nsISupports and sometimes it's not; this class tells
     429             :   // us which it is.
     430             :   const bool mDOMObjectIsISupports;
     431             : 
     432             :   const NativePropertyHooks* mNativeHooks;
     433             : 
     434             :   // A callback to find the associated global for our C++ object.  Note that
     435             :   // this is used in cases when that global is _changing_, so it will not match
     436             :   // the global of the JSObject* passed in to this function!
     437             :   AssociatedGlobalGetter mGetAssociatedGlobal;
     438             :   ProtoHandleGetter mGetProto;
     439             : 
     440             :   // This stores the CC participant for the native, null if this class does not
     441             :   // implement cycle collection or if it inherits from nsISupports (we can get
     442             :   // the CC participant by QI'ing in that case).
     443             :   nsCycleCollectionParticipant* mParticipant;
     444             : 
     445           0 :   static const DOMJSClass* FromJSClass(const JSClass* base) {
     446           0 :     MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS);
     447       53429 :     return reinterpret_cast<const DOMJSClass*>(base);
     448             :   }
     449             : 
     450             :   static const DOMJSClass* FromJSClass(const js::Class* base) {
     451       53429 :     return FromJSClass(Jsvalify(base));
     452             :   }
     453             : 
     454        6380 :   const JSClass* ToJSClass() const { return Jsvalify(&mBase); }
     455             : };
     456             : 
     457             : // Special JSClass for DOM interface and interface prototype objects.
     458             : struct DOMIfaceAndProtoJSClass
     459             : {
     460             :   // It would be nice to just inherit from js::Class, but that precludes pure
     461             :   // compile-time initialization of the form
     462             :   // |DOMJSInterfaceAndPrototypeClass = {...};|, since C++ only allows brace
     463             :   // initialization for aggregate/POD types.
     464             :   const js::Class mBase;
     465             : 
     466             :   // Either eInterface, eInterfacePrototype, eGlobalInterfacePrototype or
     467             :   // eNamedPropertiesObject.
     468             :   DOMObjectType mType; // uint8_t
     469             : 
     470             :   // Boolean indicating whether this object wants a @@hasInstance property
     471             :   // pointing to InterfaceHasInstance defined on it.  Only ever true for the
     472             :   // eInterface case.
     473             :   bool wantsInterfaceHasInstance;
     474             : 
     475             :   const prototypes::ID mPrototypeID; // uint16_t
     476             :   const uint32_t mDepth;
     477             : 
     478             :   const NativePropertyHooks* mNativeHooks;
     479             : 
     480             :   // The value to return for toString() on this interface or interface prototype
     481             :   // object.
     482             :   const char* mToString;
     483             : 
     484             :   ProtoGetter mGetParentProto;
     485             : 
     486           0 :   static const DOMIfaceAndProtoJSClass* FromJSClass(const JSClass* base) {
     487           0 :     MOZ_ASSERT(base->flags & JSCLASS_IS_DOMIFACEANDPROTOJSCLASS);
     488        1301 :     return reinterpret_cast<const DOMIfaceAndProtoJSClass*>(base);
     489             :   }
     490             :   static const DOMIfaceAndProtoJSClass* FromJSClass(const js::Class* base) {
     491        1301 :     return FromJSClass(Jsvalify(base));
     492             :   }
     493             : 
     494             :   const JSClass* ToJSClass() const { return Jsvalify(&mBase); }
     495             : };
     496             : 
     497             : class ProtoAndIfaceCache;
     498             : 
     499             : inline bool
     500           0 : DOMGlobalHasProtoAndIFaceCache(JSObject* global)
     501             : {
     502           0 :   MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
     503             :   // This can be undefined if we GC while creating the global
     504           0 :   return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined();
     505             : }
     506             : 
     507             : inline bool
     508           0 : HasProtoAndIfaceCache(JSObject* global)
     509             : {
     510           0 :   if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
     511             :     return false;
     512             :   }
     513           0 :   return DOMGlobalHasProtoAndIFaceCache(global);
     514             : }
     515             : 
     516             : inline ProtoAndIfaceCache*
     517        9714 : GetProtoAndIfaceCache(JSObject* global)
     518             : {
     519        9714 :   MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
     520             :   return static_cast<ProtoAndIfaceCache*>(
     521             :     js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).toPrivate());
     522             : }
     523             : 
     524             : } // namespace dom
     525             : } // namespace mozilla
     526             : 
     527             : #endif /* mozilla_dom_DOMJSClass_h */

Generated by: LCOV version 1.13-14-ga5dd952