LCOV - code coverage report
Current view: top level - js/xpconnect/wrappers - XrayWrapper.h (source / functions) Hit Total Coverage
Test: output.info Lines: 24 62 38.7 %
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: 4 -*- */
       2             : /* vim: set ts=8 sts=4 et sw=4 tw=99: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef XrayWrapper_h
       8             : #define XrayWrapper_h
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : 
      12             : #include "WrapperFactory.h"
      13             : 
      14             : #include "js/Proxy.h"
      15             : #include "js/Wrapper.h"
      16             : 
      17             : // Slot where Xray functions for Web IDL methods store a pointer to
      18             : // the Xray wrapper they're associated with.
      19             : #define XRAY_DOM_FUNCTION_PARENT_WRAPPER_SLOT 0
      20             : // Slot where in debug builds Xray functions for Web IDL methods store
      21             : // a pointer to their themselves, just so we can assert that they're the
      22             : // sort of functions we expect.
      23             : #define XRAY_DOM_FUNCTION_NATIVE_SLOT_FOR_SELF 1
      24             : 
      25             : // Xray wrappers re-resolve the original native properties on the native
      26             : // object and always directly access to those properties.
      27             : // Because they work so differently from the rest of the wrapper hierarchy,
      28             : // we pull them out of the Wrapper inheritance hierarchy and create a
      29             : // little world around them.
      30             : 
      31             : class nsIPrincipal;
      32             : 
      33             : namespace xpc {
      34             : 
      35             : namespace XrayUtils {
      36             : 
      37             : bool
      38             : IsTransparent(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id);
      39             : 
      40             : bool
      41             : HasNativeProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
      42             :                   bool* hasProp);
      43             : } // namespace XrayUtils
      44             : 
      45             : enum XrayType {
      46             :     XrayForDOMObject,
      47             :     XrayForJSObject,
      48             :     XrayForOpaqueObject,
      49             :     NotXray
      50             : };
      51             : 
      52             : class XrayTraits
      53             : {
      54             : public:
      55             :     constexpr XrayTraits() {}
      56             : 
      57        1113 :     static JSObject* getTargetObject(JSObject* wrapper) {
      58        1113 :         JSObject* target = js::UncheckedUnwrap(wrapper, /* stopAtWindowProxy = */ false);
      59        1113 :         if (target)
      60        1113 :             JS::ExposeObjectToActiveJS(target);
      61        1113 :         return target;
      62             :     }
      63             : 
      64             :     // NB: resolveOwnProperty may decide whether or not to cache what it finds
      65             :     // on the holder. If the result is not cached, the lookup will happen afresh
      66             :     // for each access, which is the right thing for things like dynamic NodeList
      67             :     // properties.
      68             :     virtual bool resolveOwnProperty(JSContext* cx, JS::HandleObject wrapper,
      69             :                                     JS::HandleObject target, JS::HandleObject holder,
      70             :                                     JS::HandleId id, JS::MutableHandle<JS::PropertyDescriptor> desc);
      71             : 
      72             :     bool delete_(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
      73             :                  JS::ObjectOpResult& result) {
      74           0 :         return result.succeed();
      75             :     }
      76             : 
      77           0 :     static bool getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance,
      78             :                                 js::ESClass* cls) {
      79           0 :         return baseInstance.getBuiltinClass(cx, wrapper, cls);
      80             :     }
      81             : 
      82           0 :     static const char* className(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance) {
      83           0 :         return baseInstance.className(cx, wrapper);
      84             :     }
      85             : 
      86             :     virtual void preserveWrapper(JSObject* target) = 0;
      87             : 
      88             :     bool getExpandoObject(JSContext* cx, JS::HandleObject target,
      89             :                           JS::HandleObject consumer, JS::MutableHandleObject expandObject);
      90             :     JSObject* ensureExpandoObject(JSContext* cx, JS::HandleObject wrapper,
      91             :                                   JS::HandleObject target);
      92             : 
      93             :     // Slots for holder objects.
      94             :     enum {
      95             :         HOLDER_SLOT_CACHED_PROTO = 0,
      96             :         HOLDER_SLOT_EXPANDO = 1,
      97             :         HOLDER_SHARED_SLOT_COUNT
      98             :     };
      99             : 
     100             :     static JSObject* getHolder(JSObject* wrapper);
     101             :     JSObject* ensureHolder(JSContext* cx, JS::HandleObject wrapper);
     102             :     virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) = 0;
     103             : 
     104             :     JSObject* getExpandoChain(JS::HandleObject obj);
     105             :     JSObject* detachExpandoChain(JS::HandleObject obj);
     106             :     bool setExpandoChain(JSContext* cx, JS::HandleObject obj, JS::HandleObject chain);
     107             :     bool cloneExpandoChain(JSContext* cx, JS::HandleObject dst, JS::HandleObject srcChain);
     108             : 
     109             : protected:
     110             :     static const JSClass HolderClass;
     111             : 
     112             :     // Get the JSClass we should use for our expando object.
     113             :     virtual const JSClass* getExpandoClass(JSContext* cx,
     114             :                                            JS::HandleObject target) const;
     115             : 
     116             : private:
     117             :     bool expandoObjectMatchesConsumer(JSContext* cx, JS::HandleObject expandoObject,
     118             :                                       nsIPrincipal* consumerOrigin);
     119             : 
     120             :     // |expandoChain| is the expando chain in the wrapped object's compartment.
     121             :     // |exclusiveWrapper| is any xray that has exclusive use of the expando.
     122             :     // |cx| may be in any compartment.
     123             :     bool getExpandoObjectInternal(JSContext* cx, JSObject* expandoChain,
     124             :                                   JS::HandleObject exclusiveWrapper,
     125             :                                   nsIPrincipal* origin,
     126             :                                   JS::MutableHandleObject expandoObject);
     127             : 
     128             :     // |cx| is in the target's compartment, and |exclusiveWrapper| is any xray
     129             :     // that has exclusive use of the expando.
     130             :     JSObject* attachExpandoObject(JSContext* cx, JS::HandleObject target,
     131             :                                   JS::HandleObject exclusiveWrapper,
     132             :                                   nsIPrincipal* origin);
     133             : 
     134             :     XrayTraits(XrayTraits&) = delete;
     135             :     const XrayTraits& operator=(XrayTraits&) = delete;
     136             : };
     137             : 
     138             : class DOMXrayTraits : public XrayTraits
     139             : {
     140             : public:
     141             :     constexpr DOMXrayTraits() = default;
     142             : 
     143             :     static const XrayType Type = XrayForDOMObject;
     144             : 
     145             :     virtual bool resolveOwnProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleObject target,
     146             :                                     JS::HandleObject holder, JS::HandleId id,
     147             :                                     JS::MutableHandle<JS::PropertyDescriptor> desc) override;
     148             : 
     149             :     bool delete_(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id, JS::ObjectOpResult& result);
     150             : 
     151             :     bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
     152             :                         JS::Handle<JS::PropertyDescriptor> desc,
     153             :                         JS::Handle<JS::PropertyDescriptor> existingDesc,
     154             :                         JS::ObjectOpResult& result, bool* defined);
     155             :     virtual bool enumerateNames(JSContext* cx, JS::HandleObject wrapper, unsigned flags,
     156             :                                 JS::AutoIdVector& props);
     157             :     static bool call(JSContext* cx, JS::HandleObject wrapper,
     158             :                      const JS::CallArgs& args, const js::Wrapper& baseInstance);
     159             :     static bool construct(JSContext* cx, JS::HandleObject wrapper,
     160             :                           const JS::CallArgs& args, const js::Wrapper& baseInstance);
     161             : 
     162             :     static bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
     163             :                              JS::HandleObject target,
     164             :                              JS::MutableHandleObject protop);
     165             : 
     166             :     virtual void preserveWrapper(JSObject* target) override;
     167             : 
     168             :     virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) override;
     169             : 
     170             :     static DOMXrayTraits singleton;
     171             : 
     172             : protected:
     173             :     virtual const JSClass* getExpandoClass(JSContext* cx,
     174             :                                            JS::HandleObject target) const override;
     175             : };
     176             : 
     177             : class JSXrayTraits : public XrayTraits
     178             : {
     179             : public:
     180             :     static const XrayType Type = XrayForJSObject;
     181             : 
     182             :     virtual bool resolveOwnProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleObject target,
     183             :                                     JS::HandleObject holder, JS::HandleId id,
     184             :                                     JS::MutableHandle<JS::PropertyDescriptor> desc) override;
     185             : 
     186             :     bool delete_(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id, JS::ObjectOpResult& result);
     187             : 
     188             :     bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
     189             :                         JS::Handle<JS::PropertyDescriptor> desc,
     190             :                         JS::Handle<JS::PropertyDescriptor> existingDesc,
     191             :                         JS::ObjectOpResult& result, bool* defined);
     192             : 
     193             :     virtual bool enumerateNames(JSContext* cx, JS::HandleObject wrapper, unsigned flags,
     194             :                                 JS::AutoIdVector& props);
     195             : 
     196           0 :     static bool call(JSContext* cx, JS::HandleObject wrapper,
     197             :                      const JS::CallArgs& args, const js::Wrapper& baseInstance)
     198             :     {
     199           0 :         JSXrayTraits& self = JSXrayTraits::singleton;
     200           0 :         JS::RootedObject holder(cx, self.ensureHolder(cx, wrapper));
     201           0 :         if (xpc::JSXrayTraits::getProtoKey(holder) == JSProto_Function)
     202           0 :             return baseInstance.call(cx, wrapper, args);
     203             : 
     204           0 :         JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
     205           0 :         js::ReportIsNotFunction(cx, v);
     206             :         return false;
     207             :     }
     208             : 
     209             :     static bool construct(JSContext* cx, JS::HandleObject wrapper,
     210             :                           const JS::CallArgs& args, const js::Wrapper& baseInstance);
     211             : 
     212          18 :     bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
     213             :                       JS::HandleObject target,
     214             :                       JS::MutableHandleObject protop)
     215             :     {
     216          36 :         JS::RootedObject holder(cx, ensureHolder(cx, wrapper));
     217          18 :         JSProtoKey key = getProtoKey(holder);
     218          18 :         if (isPrototype(holder)) {
     219           5 :             JSProtoKey protoKey = js::InheritanceProtoKeyForStandardClass(key);
     220           5 :             if (protoKey == JSProto_Null) {
     221           3 :                 protop.set(nullptr);
     222           3 :                 return true;
     223             :             }
     224             :             key = protoKey;
     225             :         }
     226             : 
     227             :         {
     228          45 :             JSAutoRealm ar(cx, target);
     229          15 :             if (!JS_GetClassPrototype(cx, key, protop))
     230           0 :                 return false;
     231             :         }
     232          15 :         return JS_WrapObject(cx, protop);
     233             :     }
     234             : 
     235           0 :     virtual void preserveWrapper(JSObject* target) override {
     236             :         // In the case of pure JS objects, there is no underlying object, and
     237             :         // the target is the canonical representation of state. If it gets
     238             :         // collected, then expandos and such should be collected too. So there's
     239             :         // nothing to do here.
     240           0 :     }
     241             : 
     242             :     enum {
     243             :         SLOT_PROTOKEY = HOLDER_SHARED_SLOT_COUNT,
     244             :         SLOT_ISPROTOTYPE,
     245             :         SLOT_CONSTRUCTOR_FOR,
     246             :         SLOT_COUNT
     247             :     };
     248             :     virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) override;
     249             : 
     250         180 :     static JSProtoKey getProtoKey(JSObject* holder) {
     251         180 :         int32_t key = js::GetReservedSlot(holder, SLOT_PROTOKEY).toInt32();
     252         180 :         return static_cast<JSProtoKey>(key);
     253             :     }
     254             : 
     255           1 :     static bool isPrototype(JSObject* holder) {
     256         172 :         return js::GetReservedSlot(holder, SLOT_ISPROTOTYPE).toBoolean();
     257             :     }
     258             : 
     259           1 :     static JSProtoKey constructorFor(JSObject* holder) {
     260          12 :         int32_t key = js::GetReservedSlot(holder, SLOT_CONSTRUCTOR_FOR).toInt32();
     261          12 :         return static_cast<JSProtoKey>(key);
     262             :     }
     263             : 
     264             :     // Operates in the wrapper compartment.
     265             :     static bool getOwnPropertyFromWrapperIfSafe(JSContext* cx,
     266             :                                                 JS::HandleObject wrapper,
     267             :                                                 JS::HandleId id,
     268             :                                                 JS::MutableHandle<JS::PropertyDescriptor> desc);
     269             : 
     270             :     // Like the above, but operates in the target compartment.
     271             :     static bool getOwnPropertyFromTargetIfSafe(JSContext* cx,
     272             :                                                JS::HandleObject target,
     273             :                                                JS::HandleObject wrapper,
     274             :                                                JS::HandleId id,
     275             :                                                JS::MutableHandle<JS::PropertyDescriptor> desc);
     276             : 
     277             :     static const JSClass HolderClass;
     278             :     static JSXrayTraits singleton;
     279             : };
     280             : 
     281             : // These traits are used when the target is not Xrayable and we therefore want
     282             : // to make it opaque modulo the usual Xray machinery (like expandos and
     283             : // .wrappedJSObject).
     284             : class OpaqueXrayTraits : public XrayTraits
     285             : {
     286             : public:
     287             :     static const XrayType Type = XrayForOpaqueObject;
     288             : 
     289             :     virtual bool resolveOwnProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleObject target,
     290             :                                     JS::HandleObject holder, JS::HandleId id,
     291             :                                     JS::MutableHandle<JS::PropertyDescriptor> desc) override;
     292             : 
     293             :     bool defineProperty(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id,
     294             :                         JS::Handle<JS::PropertyDescriptor> desc,
     295             :                         JS::Handle<JS::PropertyDescriptor> existingDesc,
     296             :                         JS::ObjectOpResult& result, bool* defined)
     297             :     {
     298           0 :         *defined = false;
     299             :         return true;
     300             :     }
     301             : 
     302           0 :     virtual bool enumerateNames(JSContext* cx, JS::HandleObject wrapper, unsigned flags,
     303             :                                 JS::AutoIdVector& props)
     304             :     {
     305           0 :         return true;
     306             :     }
     307             : 
     308           0 :     static bool call(JSContext* cx, JS::HandleObject wrapper,
     309             :                      const JS::CallArgs& args, const js::Wrapper& baseInstance)
     310             :     {
     311           0 :         JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
     312           0 :         js::ReportIsNotFunction(cx, v);
     313           0 :         return false;
     314             :     }
     315             : 
     316           0 :     static bool construct(JSContext* cx, JS::HandleObject wrapper,
     317             :                           const JS::CallArgs& args, const js::Wrapper& baseInstance)
     318             :     {
     319           0 :         JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
     320           0 :         js::ReportIsNotFunction(cx, v);
     321           0 :         return false;
     322             :     }
     323             : 
     324           0 :     bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
     325             :                       JS::HandleObject target,
     326             :                       JS::MutableHandleObject protop)
     327             :     {
     328             :         // Opaque wrappers just get targetGlobal.Object.prototype as their
     329             :         // prototype. This is preferable to using a null prototype because it
     330             :         // lets things like |toString| and |__proto__| work.
     331             :         {
     332           0 :             JSAutoRealm ar(cx, target);
     333           0 :             if (!JS_GetClassPrototype(cx, JSProto_Object, protop))
     334           0 :                 return false;
     335             :         }
     336           0 :         return JS_WrapObject(cx, protop);
     337             :     }
     338             : 
     339             :     static bool getBuiltinClass(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance,
     340             :                                 js::ESClass* cls) {
     341           0 :         *cls = js::ESClass::Other;
     342             :         return true;
     343             :     }
     344             : 
     345             :     static const char* className(JSContext* cx, JS::HandleObject wrapper, const js::Wrapper& baseInstance) {
     346             :         return "Opaque";
     347             :     }
     348             : 
     349           0 :     virtual void preserveWrapper(JSObject* target) override { }
     350             : 
     351           0 :     virtual JSObject* createHolder(JSContext* cx, JSObject* wrapper) override
     352             :     {
     353           0 :         return JS_NewObjectWithGivenProto(cx, &HolderClass, nullptr);
     354             :     }
     355             : 
     356             :     static OpaqueXrayTraits singleton;
     357             : };
     358             : 
     359             : XrayType GetXrayType(JSObject* obj);
     360             : XrayTraits* GetXrayTraits(JSObject* obj);
     361             : 
     362             : template <typename Base, typename Traits>
     363             : class XrayWrapper : public Base {
     364             :     static_assert(mozilla::IsBaseOf<js::BaseProxyHandler, Base>::value,
     365             :                   "Base *must* derive from js::BaseProxyHandler");
     366             :   public:
     367           0 :     constexpr explicit XrayWrapper(unsigned flags)
     368           0 :       : Base(flags | WrapperFactory::IS_XRAY_WRAPPER_FLAG, /* aHasPrototype = */ true)
     369           0 :     { };
     370             : 
     371             :     /* Standard internal methods. */
     372             :     virtual bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     373             :                                           JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
     374             :     virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     375             :                                 JS::Handle<JS::PropertyDescriptor> desc,
     376             :                                 JS::ObjectOpResult& result) const override;
     377             :     virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
     378             :                                  JS::AutoIdVector& props) const override;
     379             :     virtual bool delete_(JSContext* cx, JS::Handle<JSObject*> wrapper,
     380             :                          JS::Handle<jsid> id, JS::ObjectOpResult& result) const override;
     381             :     virtual JSObject* enumerate(JSContext* cx, JS::Handle<JSObject*> wrapper) const override;
     382             :     virtual bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
     383             :                               JS::MutableHandleObject protop) const override;
     384             :     virtual bool setPrototype(JSContext* cx, JS::HandleObject wrapper,
     385             :                               JS::HandleObject proto, JS::ObjectOpResult& result) const override;
     386             :     virtual bool getPrototypeIfOrdinary(JSContext* cx, JS::HandleObject wrapper, bool* isOrdinary,
     387             :                                         JS::MutableHandleObject protop) const override;
     388             :     virtual bool setImmutablePrototype(JSContext* cx, JS::HandleObject wrapper,
     389             :                                        bool* succeeded) const override;
     390             :     virtual bool preventExtensions(JSContext* cx, JS::Handle<JSObject*> wrapper,
     391             :                                    JS::ObjectOpResult& result) const override;
     392             :     virtual bool isExtensible(JSContext* cx, JS::Handle<JSObject*> wrapper, bool* extensible) const override;
     393             :     virtual bool has(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     394             :                      bool* bp) const override;
     395             :     virtual bool get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::HandleValue receiver,
     396             :                      JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
     397             :     virtual bool set(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     398             :                      JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
     399             :                      JS::ObjectOpResult& result) const override;
     400             :     virtual bool call(JSContext* cx, JS::Handle<JSObject*> wrapper,
     401             :                       const JS::CallArgs& args) const override;
     402             :     virtual bool construct(JSContext* cx, JS::Handle<JSObject*> wrapper,
     403             :                            const JS::CallArgs& args) const override;
     404             : 
     405             :     /* SpiderMonkey extensions. */
     406             :     virtual bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     407             :                                        JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
     408             :     virtual bool hasOwn(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
     409             :                         bool* bp) const override;
     410             :     virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
     411             :                                               JS::AutoIdVector& props) const override;
     412             : 
     413             :     virtual bool getBuiltinClass(JSContext* cx, JS::HandleObject wapper, js::ESClass* cls) const override;
     414             :     virtual const char* className(JSContext* cx, JS::HandleObject proxy) const override;
     415             : 
     416             :     static const XrayWrapper singleton;
     417             : 
     418             :   protected:
     419             :     bool getPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper, unsigned flags,
     420             :                          JS::AutoIdVector& props) const;
     421             : };
     422             : 
     423             : #define PermissiveXrayDOM xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::DOMXrayTraits>
     424             : #define SecurityXrayDOM xpc::XrayWrapper<js::CrossCompartmentSecurityWrapper, xpc::DOMXrayTraits>
     425             : #define PermissiveXrayJS xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::JSXrayTraits>
     426             : #define PermissiveXrayOpaque xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::OpaqueXrayTraits>
     427             : 
     428             : extern template class PermissiveXrayDOM;
     429             : extern template class SecurityXrayDOM;
     430             : extern template class PermissiveXrayJS;
     431             : extern template class PermissiveXrayOpaque;
     432             : 
     433             : /*
     434             :  * Slots for Xray expando objects.  See comments in XrayWrapper.cpp for details
     435             :  * of how these get used; we mostly want the value of JSSLOT_EXPANDO_COUNT here.
     436             :  */
     437             : enum ExpandoSlots {
     438             :     JSSLOT_EXPANDO_NEXT = 0,
     439             :     JSSLOT_EXPANDO_ORIGIN,
     440             :     JSSLOT_EXPANDO_EXCLUSIVE_WRAPPER_HOLDER,
     441             :     JSSLOT_EXPANDO_PROTOTYPE,
     442             :     JSSLOT_EXPANDO_COUNT
     443             : };
     444             : 
     445             : extern const JSClassOps XrayExpandoObjectClassOps;
     446             : 
     447             : /*
     448             :  * Clear the given slot on all Xray expandos for the given object.
     449             :  *
     450             :  * No-op when called on non-main threads (where Xrays don't exist).
     451             :  */
     452             : void
     453             : ClearXrayExpandoSlots(JSObject* target, size_t slotIndex);
     454             : 
     455             : /*
     456             :  * Ensure the given wrapper has an expando object and return it.  This can
     457             :  * return null on failure.  Will only be called when "wrapper" is an Xray for a
     458             :  * DOM object.
     459             :  */
     460             : JSObject*
     461             : EnsureXrayExpandoObject(JSContext* cx, JS::HandleObject wrapper);
     462             : 
     463             : // Information about xrays for use by the JITs.
     464             : extern js::XrayJitInfo gXrayJitInfo;
     465             : 
     466             : } // namespace xpc
     467             : 
     468             : #endif

Generated by: LCOV version 1.13-14-ga5dd952