LCOV - code coverage report
Current view: top level - js/src/vm - ProxyObject.h (source / functions) Hit Total Coverage
Test: output.info Lines: 39 41 95.1 %
Date: 2017-07-14 16:53:18 Functions: 17 18 94.4 %
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 vm_ProxyObject_h
       8             : #define vm_ProxyObject_h
       9             : 
      10             : #include "js/Proxy.h"
      11             : #include "vm/ShapedObject.h"
      12             : 
      13             : namespace js {
      14             : 
      15             : /**
      16             :  * This is the base class for the various kinds of proxy objects.  It's never
      17             :  * instantiated.
      18             :  *
      19             :  * Proxy objects use ShapedObject::shape_ primarily to record flags.  Property
      20             :  * information, &c. is all dynamically computed.
      21             :  */
      22             : class ProxyObject : public ShapedObject
      23             : {
      24             :     // GetProxyDataLayout computes the address of this field.
      25             :     detail::ProxyDataLayout data;
      26             : 
      27             :     void static_asserts() {
      28             :         static_assert(sizeof(ProxyObject) == sizeof(JSObject_Slots0),
      29             :                       "proxy object size must match GC thing size");
      30             :         static_assert(offsetof(ProxyObject, data) == detail::ProxyDataOffset,
      31             :                       "proxy object layout must match shadow interface");
      32             :         static_assert(offsetof(ProxyObject, data.reservedSlots) == offsetof(shadow::Object, slots),
      33             :                       "Proxy reservedSlots must overlay native object slots field");
      34             :     }
      35             : 
      36             :     static JS::Result<ProxyObject*, JS::OOM&>
      37             :     create(JSContext* cx, const js::Class* clasp, Handle<TaggedProto> proto,
      38             :            js::gc::AllocKind allocKind, js::NewObjectKind newKind);
      39             : 
      40             :   public:
      41             :     static ProxyObject* New(JSContext* cx, const BaseProxyHandler* handler, HandleValue priv,
      42             :                             TaggedProto proto_, const ProxyOptions& options);
      43             : 
      44             :     // Proxies usually store their ProxyValueArray inline in the object.
      45             :     // There's one unfortunate exception: when a proxy is swapped with another
      46             :     // object, and the sizes don't match, we malloc the ProxyValueArray.
      47       15662 :     void* inlineDataStart() const {
      48       15662 :         return (void*)(uintptr_t(this) + sizeof(ProxyObject));
      49             :     }
      50        4222 :     bool usingInlineValueArray() const {
      51        4222 :         return data.values() == inlineDataStart();
      52             :     }
      53       11440 :     void setInlineValueArray() {
      54       11440 :         data.reservedSlots = &reinterpret_cast<detail::ProxyValueArray*>(inlineDataStart())->reservedSlots;
      55       11440 :     }
      56             :     MOZ_MUST_USE bool initExternalValueArrayAfterSwap(JSContext* cx, const Vector<Value>& values);
      57             : 
      58       83524 :     const Value& private_() {
      59       83524 :         return GetProxyPrivate(this);
      60             :     }
      61             : 
      62             :     void setCrossCompartmentPrivate(const Value& priv);
      63             :     void setSameCompartmentPrivate(const Value& priv);
      64             : 
      65       11500 :     GCPtrValue* slotOfPrivate() {
      66       11500 :         return reinterpret_cast<GCPtrValue*>(&detail::GetProxyDataLayout(this)->values()->privateSlot);
      67             :     }
      68             : 
      69       76318 :     JSObject* target() const {
      70       76318 :         return const_cast<ProxyObject*>(this)->private_().toObjectOrNull();
      71             :     }
      72             : 
      73       77790 :     const BaseProxyHandler* handler() const {
      74       77790 :         return GetProxyHandler(const_cast<ProxyObject*>(this));
      75             :     }
      76             : 
      77          54 :     void setHandler(const BaseProxyHandler* handler) {
      78          54 :         SetProxyHandler(this, handler);
      79          54 :     }
      80             : 
      81          19 :     static size_t offsetOfReservedSlots() {
      82          19 :         return offsetof(ProxyObject, data.reservedSlots);
      83             :     }
      84          24 :     static size_t offsetOfHandler() {
      85          24 :         return offsetof(ProxyObject, data.handler);
      86             :     }
      87             : 
      88       11476 :     size_t numReservedSlots() const {
      89       11476 :         return JSCLASS_RESERVED_SLOTS(getClass());
      90             :     }
      91          71 :     const Value& reservedSlot(size_t n) const {
      92          71 :         return GetProxyReservedSlot(const_cast<ProxyObject*>(this), n);
      93             :     }
      94             : 
      95          28 :     void setReservedSlot(size_t n, const Value& extra) {
      96          28 :         SetProxyReservedSlot(this, n, extra);
      97          28 :     }
      98             : 
      99             :     gc::AllocKind allocKindForTenure() const;
     100             : 
     101             :   private:
     102        2113 :     GCPtrValue* reservedSlotPtr(size_t n) {
     103        2113 :         return reinterpret_cast<GCPtrValue*>(&detail::GetProxyDataLayout(this)->reservedSlots->slots[n]);
     104             :     }
     105             : 
     106        9333 :     static bool isValidProxyClass(const Class* clasp) {
     107             :         // Since we can take classes from the outside, make sure that they
     108             :         // are "sane". They have to quack enough like proxies for us to belive
     109             :         // they should be treated as such.
     110             : 
     111             :         // Proxy classes are not allowed to have call or construct hooks directly. Their
     112             :         // callability is instead decided by handler()->isCallable().
     113       18666 :         return clasp->isProxy() &&
     114       18666 :                clasp->isTrace(ProxyObject::trace) &&
     115       27999 :                !clasp->getCall() && !clasp->getConstruct();
     116             :     }
     117             : 
     118             :   public:
     119             :     static unsigned grayLinkReservedSlot(JSObject* obj);
     120             : 
     121             :     void renew(const BaseProxyHandler* handler, const Value& priv);
     122             : 
     123             :     static void trace(JSTracer* trc, JSObject* obj);
     124             : 
     125             :     void nuke();
     126             : 
     127             :     // There is no class_ member to force specialization of JSObject::is<T>().
     128             :     // The implementation in JSObject is incorrect for proxies since it doesn't
     129             :     // take account of the handler type.
     130             :     static const Class proxyClass;
     131             : };
     132             : 
     133             : inline bool
     134           0 : IsProxyClass(const Class* clasp)
     135             : {
     136           0 :     return clasp->isProxy();
     137             : }
     138             : 
     139             : bool IsDerivedProxyObject(const JSObject* obj, const js::BaseProxyHandler* handler);
     140             : 
     141             : } // namespace js
     142             : 
     143             : template<>
     144             : inline bool
     145      638790 : JSObject::is<js::ProxyObject>() const
     146             : {
     147             :     // Note: this method is implemented in terms of the IsProxy() friend API
     148             :     // functions to ensure the implementations are tied together.
     149             :     // Note 2: this specialization isn't used for subclasses of ProxyObject
     150             :     // which must supply their own implementation.
     151      638790 :     return js::IsProxy(const_cast<JSObject*>(this));
     152             : }
     153             : 
     154             : inline bool
     155      118409 : js::IsDerivedProxyObject(const JSObject* obj, const js::BaseProxyHandler* handler) {
     156      118409 :     return obj->is<js::ProxyObject>() && obj->as<js::ProxyObject>().handler() == handler;
     157             : }
     158             : 
     159             : #endif /* vm_ProxyObject_h */

Generated by: LCOV version 1.13