LCOV - code coverage report
Current view: top level - dom/bindings - TypedArray.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 106 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 195 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_TypedArray_h
       8             : #define mozilla_dom_TypedArray_h
       9             : 
      10             : #include "jsapi.h"
      11             : #include "jsfriendapi.h"
      12             : #include "js/RootingAPI.h"
      13             : #include "js/TracingAPI.h"
      14             : #include "mozilla/Attributes.h"
      15             : #include "mozilla/Move.h"
      16             : #include "mozilla/dom/BindingDeclarations.h"
      17             : #include "nsWrapperCache.h"
      18             : 
      19             : namespace mozilla {
      20             : namespace dom {
      21             : 
      22             : /*
      23             :  * Class that just handles the JSObject storage and tracing for typed arrays
      24             :  */
      25             : struct TypedArrayObjectStorage : AllTypedArraysBase {
      26             : protected:
      27             :   JSObject* mTypedObj;
      28             :   JSObject* mWrappedObj;
      29             : 
      30           0 :   TypedArrayObjectStorage()
      31           0 :     : mTypedObj(nullptr),
      32           0 :       mWrappedObj(nullptr)
      33             :   {
      34           0 :   }
      35             : 
      36             :   TypedArrayObjectStorage(TypedArrayObjectStorage&& aOther)
      37             :     : mTypedObj(aOther.mTypedObj),
      38             :       mWrappedObj(aOther.mWrappedObj)
      39             :   {
      40             :     aOther.mTypedObj = nullptr;
      41             :     aOther.mWrappedObj = nullptr;
      42             :   }
      43             : 
      44             : public:
      45           0 :   inline void TraceSelf(JSTracer* trc)
      46             :   {
      47           0 :     JS::UnsafeTraceRoot(trc, &mTypedObj, "TypedArray.mTypedObj");
      48           0 :     JS::UnsafeTraceRoot(trc, &mWrappedObj, "TypedArray.mWrappedObj");
      49           0 :   }
      50             : 
      51             : private:
      52             :   TypedArrayObjectStorage(const TypedArrayObjectStorage&) = delete;
      53             : };
      54             : 
      55             : /*
      56             :  * Various typed array classes for argument conversion.  We have a base class
      57             :  * that has a way of initializing a TypedArray from an existing typed array, and
      58             :  * a subclass of the base class that supports creation of a relevant typed array
      59             :  * or array buffer object.
      60             :  */
      61             : template<typename T,
      62             :          JSObject* UnwrapArray(JSObject*),
      63             :          void GetLengthAndDataAndSharedness(JSObject*, uint32_t*, bool*, T**)>
      64             : struct TypedArray_base : public TypedArrayObjectStorage {
      65             :   typedef T element_type;
      66             : 
      67           0 :   TypedArray_base()
      68             :     : mData(nullptr),
      69             :       mLength(0),
      70             :       mShared(false),
      71           0 :       mComputed(false)
      72             :   {
      73           0 :   }
      74             : 
      75             :   TypedArray_base(TypedArray_base&& aOther)
      76             :     : TypedArrayObjectStorage(Move(aOther)),
      77             :       mData(aOther.mData),
      78             :       mLength(aOther.mLength),
      79             :       mShared(aOther.mShared),
      80             :       mComputed(aOther.mComputed)
      81             :   {
      82             :     aOther.mData = nullptr;
      83             :     aOther.mLength = 0;
      84             :     aOther.mShared = false;
      85             :     aOther.mComputed = false;
      86             :   }
      87             : 
      88             : private:
      89             :   mutable T* mData;
      90             :   mutable uint32_t mLength;
      91             :   mutable bool mShared;
      92             :   mutable bool mComputed;
      93             : 
      94             : public:
      95           0 :   inline bool Init(JSObject* obj)
      96             :   {
      97           0 :     MOZ_ASSERT(!inited());
      98           0 :     mTypedObj = mWrappedObj = UnwrapArray(obj);
      99           0 :     return inited();
     100             :   }
     101             : 
     102           0 :   inline bool inited() const {
     103           0 :     return !!mTypedObj;
     104             :   }
     105             : 
     106             :   // About shared memory:
     107             :   //
     108             :   // Any DOM TypedArray as well as any DOM ArrayBufferView can map the
     109             :   // memory of either a JS ArrayBuffer or a JS SharedArrayBuffer.  If
     110             :   // the TypedArray maps a SharedArrayBuffer the Length() and Data()
     111             :   // accessors on the DOM view will return zero and nullptr; to get
     112             :   // the actual length and data, call the LengthAllowShared() and
     113             :   // DataAllowShared() accessors instead.
     114             :   //
     115             :   // Two methods are available for determining if a DOM view maps
     116             :   // shared memory.  The IsShared() method is cheap and can be called
     117             :   // if the view has been computed; the JS_GetTypedArraySharedness()
     118             :   // method is slightly more expensive and can be called on the Obj()
     119             :   // value if the view may not have been computed and if the value is
     120             :   // known to represent a JS TypedArray.
     121             :   //
     122             :   // (Just use JS_IsSharedArrayBuffer() to test if any object is of
     123             :   // that type.)
     124             :   //
     125             :   // Code that elects to allow views that map shared memory to be used
     126             :   // -- ie, code that "opts in to shared memory" -- should generally
     127             :   // not access the raw data buffer with standard C++ mechanisms as
     128             :   // that creates the possibility of C++ data races, which is
     129             :   // undefined behavior.  The JS engine will eventually export (bug
     130             :   // 1225033) a suite of methods that avoid undefined behavior.
     131             :   //
     132             :   // Callers of Obj() that do not opt in to shared memory can produce
     133             :   // better diagnostics by checking whether the JSObject in fact maps
     134             :   // shared memory and throwing an error if it does.  However, it is
     135             :   // safe to use the value of Obj() without such checks.
     136             :   //
     137             :   // The DOM TypedArray abstraction prevents the underlying buffer object
     138             :   // from being accessed directly, but JS_GetArrayBufferViewBuffer(Obj())
     139             :   // will obtain the buffer object.  Code that calls that function must
     140             :   // not assume the returned buffer is an ArrayBuffer.  That is guarded
     141             :   // against by an out parameter on that call that communicates the
     142             :   // sharedness of the buffer.
     143             :   //
     144             :   // Finally, note that the buffer memory of a SharedArrayBuffer is
     145             :   // not detachable.
     146             : 
     147           0 :   inline bool IsShared() const {
     148           0 :     MOZ_ASSERT(mComputed);
     149           0 :     return mShared;
     150             :   }
     151             : 
     152           0 :   inline T *Data() const {
     153           0 :     MOZ_ASSERT(mComputed);
     154           0 :     if (mShared)
     155           0 :       return nullptr;
     156           0 :     return mData;
     157             :   }
     158             : 
     159           0 :   inline T *DataAllowShared() const {
     160           0 :     MOZ_ASSERT(mComputed);
     161           0 :     return mData;
     162             :   }
     163             : 
     164           0 :   inline uint32_t Length() const {
     165           0 :     MOZ_ASSERT(mComputed);
     166           0 :     if (mShared)
     167           0 :       return 0;
     168           0 :     return mLength;
     169             :   }
     170             : 
     171           0 :   inline uint32_t LengthAllowShared() const {
     172           0 :     MOZ_ASSERT(mComputed);
     173           0 :     return mLength;
     174             :   }
     175             : 
     176           0 :   inline JSObject *Obj() const {
     177           0 :     MOZ_ASSERT(inited());
     178           0 :     return mWrappedObj;
     179             :   }
     180             : 
     181           0 :   inline bool WrapIntoNewCompartment(JSContext* cx)
     182             :   {
     183           0 :     return JS_WrapObject(cx,
     184           0 :       JS::MutableHandle<JSObject*>::fromMarkedLocation(&mWrappedObj));
     185             :   }
     186             : 
     187           0 :   inline void ComputeLengthAndData() const
     188             :   {
     189           0 :     MOZ_ASSERT(inited());
     190           0 :     MOZ_ASSERT(!mComputed);
     191           0 :     GetLengthAndDataAndSharedness(mTypedObj, &mLength, &mShared, &mData);
     192           0 :     mComputed = true;
     193           0 :   }
     194             : 
     195             : private:
     196             :   TypedArray_base(const TypedArray_base&) = delete;
     197             : };
     198             : 
     199             : template<typename T,
     200             :          JSObject* UnwrapArray(JSObject*),
     201             :          T* GetData(JSObject*, bool* isShared, const JS::AutoCheckCannotGC&),
     202             :          void GetLengthAndDataAndSharedness(JSObject*, uint32_t*, bool*, T**),
     203             :          JSObject* CreateNew(JSContext*, uint32_t)>
     204             : struct TypedArray
     205             :   : public TypedArray_base<T, UnwrapArray, GetLengthAndDataAndSharedness>
     206             : {
     207             : private:
     208             :   typedef TypedArray_base<T, UnwrapArray, GetLengthAndDataAndSharedness> Base;
     209             : 
     210             : public:
     211           0 :   TypedArray()
     212           0 :     : Base()
     213           0 :   {}
     214             : 
     215             :   TypedArray(TypedArray&& aOther)
     216             :     : Base(Move(aOther))
     217             :   {
     218             :   }
     219             : 
     220             :   static inline JSObject*
     221           0 :   Create(JSContext* cx, nsWrapperCache* creator, uint32_t length,
     222             :          const T* data = nullptr) {
     223           0 :     JS::Rooted<JSObject*> creatorWrapper(cx);
     224           0 :     Maybe<JSAutoCompartment> ac;
     225           0 :     if (creator && (creatorWrapper = creator->GetWrapperPreserveColor())) {
     226           0 :       ac.emplace(cx, creatorWrapper);
     227             :     }
     228             : 
     229           0 :     return CreateCommon(cx, length, data);
     230             :   }
     231             : 
     232             :   static inline JSObject*
     233           0 :   Create(JSContext* cx, uint32_t length, const T* data = nullptr) {
     234           0 :     return CreateCommon(cx, length, data);
     235             :   }
     236             : 
     237             : private:
     238             :   static inline JSObject*
     239           0 :   CreateCommon(JSContext* cx, uint32_t length, const T* data) {
     240           0 :     JSObject* obj = CreateNew(cx, length);
     241           0 :     if (!obj) {
     242           0 :       return nullptr;
     243             :     }
     244           0 :     if (data) {
     245           0 :       JS::AutoCheckCannotGC nogc;
     246             :       bool isShared;
     247           0 :       T* buf = static_cast<T*>(GetData(obj, &isShared, nogc));
     248             :       // Data will not be shared, until a construction protocol exists
     249             :       // for constructing shared data.
     250           0 :       MOZ_ASSERT(!isShared);
     251           0 :       memcpy(buf, data, length*sizeof(T));
     252             :     }
     253           0 :     return obj;
     254             :   }
     255             : 
     256             :   TypedArray(const TypedArray&) = delete;
     257             : };
     258             : 
     259             : template<JSObject* UnwrapArray(JSObject*),
     260             :          void GetLengthAndDataAndSharedness(JSObject*, uint32_t*, bool*,
     261             :                                             uint8_t**),
     262             :          js::Scalar::Type GetViewType(JSObject*)>
     263             : struct ArrayBufferView_base
     264             :   : public TypedArray_base<uint8_t, UnwrapArray, GetLengthAndDataAndSharedness>
     265             : {
     266             : private:
     267             :   typedef TypedArray_base<uint8_t, UnwrapArray, GetLengthAndDataAndSharedness>
     268             :           Base;
     269             : 
     270             : public:
     271           0 :   ArrayBufferView_base()
     272           0 :     : Base()
     273             :   {
     274           0 :   }
     275             : 
     276             :   ArrayBufferView_base(ArrayBufferView_base&& aOther)
     277             :     : Base(Move(aOther)),
     278             :       mType(aOther.mType)
     279             :   {
     280             :     aOther.mType = js::Scalar::MaxTypedArrayViewType;
     281             :   }
     282             : 
     283             : private:
     284             :   js::Scalar::Type mType;
     285             : 
     286             : public:
     287           0 :   inline bool Init(JSObject* obj)
     288             :   {
     289           0 :     if (!Base::Init(obj)) {
     290           0 :       return false;
     291             :     }
     292             : 
     293           0 :     mType = GetViewType(this->Obj());
     294           0 :     return true;
     295             :   }
     296             : 
     297           0 :   inline js::Scalar::Type Type() const
     298             :   {
     299           0 :     MOZ_ASSERT(this->inited());
     300           0 :     return mType;
     301             :   }
     302             : };
     303             : 
     304             : typedef TypedArray<int8_t, js::UnwrapInt8Array, JS_GetInt8ArrayData,
     305             :                    js::GetInt8ArrayLengthAndData, JS_NewInt8Array>
     306             :         Int8Array;
     307             : typedef TypedArray<uint8_t, js::UnwrapUint8Array, JS_GetUint8ArrayData,
     308             :                    js::GetUint8ArrayLengthAndData, JS_NewUint8Array>
     309             :         Uint8Array;
     310             : typedef TypedArray<uint8_t, js::UnwrapUint8ClampedArray, JS_GetUint8ClampedArrayData,
     311             :                    js::GetUint8ClampedArrayLengthAndData, JS_NewUint8ClampedArray>
     312             :         Uint8ClampedArray;
     313             : typedef TypedArray<int16_t, js::UnwrapInt16Array, JS_GetInt16ArrayData,
     314             :                    js::GetInt16ArrayLengthAndData, JS_NewInt16Array>
     315             :         Int16Array;
     316             : typedef TypedArray<uint16_t, js::UnwrapUint16Array, JS_GetUint16ArrayData,
     317             :                    js::GetUint16ArrayLengthAndData, JS_NewUint16Array>
     318             :         Uint16Array;
     319             : typedef TypedArray<int32_t, js::UnwrapInt32Array, JS_GetInt32ArrayData,
     320             :                    js::GetInt32ArrayLengthAndData, JS_NewInt32Array>
     321             :         Int32Array;
     322             : typedef TypedArray<uint32_t, js::UnwrapUint32Array, JS_GetUint32ArrayData,
     323             :                    js::GetUint32ArrayLengthAndData, JS_NewUint32Array>
     324             :         Uint32Array;
     325             : typedef TypedArray<float, js::UnwrapFloat32Array, JS_GetFloat32ArrayData,
     326             :                    js::GetFloat32ArrayLengthAndData, JS_NewFloat32Array>
     327             :         Float32Array;
     328             : typedef TypedArray<double, js::UnwrapFloat64Array, JS_GetFloat64ArrayData,
     329             :                    js::GetFloat64ArrayLengthAndData, JS_NewFloat64Array>
     330             :         Float64Array;
     331             : typedef ArrayBufferView_base<js::UnwrapArrayBufferView,
     332             :                              js::GetArrayBufferViewLengthAndData,
     333             :                              JS_GetArrayBufferViewType>
     334             :         ArrayBufferView;
     335             : typedef TypedArray<uint8_t, js::UnwrapArrayBuffer, JS_GetArrayBufferData,
     336             :                    js::GetArrayBufferLengthAndData, JS_NewArrayBuffer>
     337             :         ArrayBuffer;
     338             : 
     339             : typedef TypedArray<uint8_t, js::UnwrapSharedArrayBuffer, JS_GetSharedArrayBufferData,
     340             :                    js::GetSharedArrayBufferLengthAndData, JS_NewSharedArrayBuffer>
     341             :         SharedArrayBuffer;
     342             : 
     343             : // A class for converting an nsTArray to a TypedArray
     344             : // Note: A TypedArrayCreator must not outlive the nsTArray it was created from.
     345             : //       So this is best used to pass from things that understand nsTArray to
     346             : //       things that understand TypedArray, as with ToJSValue.
     347             : template<typename TypedArrayType>
     348             : class TypedArrayCreator
     349             : {
     350             :   typedef nsTArray<typename TypedArrayType::element_type> ArrayType;
     351             : 
     352             :   public:
     353           0 :     explicit TypedArrayCreator(const ArrayType& aArray)
     354           0 :       : mArray(aArray)
     355           0 :     {}
     356             : 
     357           0 :     JSObject* Create(JSContext* aCx) const
     358             :     {
     359           0 :       return TypedArrayType::Create(aCx, mArray.Length(), mArray.Elements());
     360             :     }
     361             : 
     362             :   private:
     363             :     const ArrayType& mArray;
     364             : };
     365             : 
     366             : // A class for rooting an existing TypedArray struct
     367             : template<typename ArrayType>
     368           0 : class MOZ_RAII TypedArrayRooter : private JS::CustomAutoRooter
     369             : {
     370             : public:
     371             :   template <typename CX>
     372           0 :   TypedArrayRooter(const CX& cx,
     373             :                    ArrayType* aArray MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
     374           0 :     JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
     375           0 :     mArray(aArray)
     376             :   {
     377           0 :   }
     378             : 
     379           0 :   virtual void trace(JSTracer* trc) override
     380             :   {
     381           0 :     mArray->TraceSelf(trc);
     382           0 :   }
     383             : 
     384             : private:
     385             :   TypedArrayObjectStorage* const mArray;
     386             : };
     387             : 
     388             : // And a specialization for dealing with nullable typed arrays
     389             : template<typename Inner> struct Nullable;
     390             : template<typename ArrayType>
     391           0 : class MOZ_RAII TypedArrayRooter<Nullable<ArrayType> > :
     392             :     private JS::CustomAutoRooter
     393             : {
     394             : public:
     395             :   template <typename CX>
     396           0 :   TypedArrayRooter(const CX& cx,
     397             :                    Nullable<ArrayType>* aArray MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
     398           0 :     JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
     399           0 :     mArray(aArray)
     400             :   {
     401           0 :   }
     402             : 
     403           0 :   virtual void trace(JSTracer* trc) override
     404             :   {
     405           0 :     if (!mArray->IsNull()) {
     406           0 :       mArray->Value().TraceSelf(trc);
     407             :     }
     408           0 :   }
     409             : 
     410             : private:
     411             :   Nullable<ArrayType>* const mArray;
     412             : };
     413             : 
     414             : // Class for easily setting up a rooted typed array object on the stack
     415             : template<typename ArrayType>
     416           0 : class MOZ_RAII RootedTypedArray final : public ArrayType,
     417             :                                         private TypedArrayRooter<ArrayType>
     418             : {
     419             : public:
     420             :   template <typename CX>
     421           0 :   explicit RootedTypedArray(const CX& cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
     422             :     ArrayType(),
     423             :     TypedArrayRooter<ArrayType>(cx, this
     424           0 :                                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
     425             :   {
     426           0 :   }
     427             : 
     428             :   template <typename CX>
     429             :   RootedTypedArray(const CX& cx, JSObject* obj MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
     430             :     ArrayType(obj),
     431             :     TypedArrayRooter<ArrayType>(cx, this
     432             :                                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
     433             :   {
     434             :   }
     435             : };
     436             : 
     437             : } // namespace dom
     438             : } // namespace mozilla
     439             : 
     440             : #endif /* mozilla_dom_TypedArray_h */

Generated by: LCOV version 1.13