dom/bindings/TypedArray.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
michael@0 2 /* vim: set ts=2 sw=2 et tw=79: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef mozilla_dom_TypedArray_h
michael@0 8 #define mozilla_dom_TypedArray_h
michael@0 9
michael@0 10 #include "jsapi.h"
michael@0 11 #include "jsfriendapi.h"
michael@0 12 #include "js/RootingAPI.h"
michael@0 13 #include "js/TracingAPI.h"
michael@0 14 #include "mozilla/Attributes.h"
michael@0 15 #include "mozilla/Move.h"
michael@0 16 #include "mozilla/dom/BindingDeclarations.h"
michael@0 17 #include "nsWrapperCache.h"
michael@0 18
michael@0 19 namespace mozilla {
michael@0 20 namespace dom {
michael@0 21
michael@0 22 /*
michael@0 23 * Class that just handles the JSObject storage and tracing for typed arrays
michael@0 24 */
michael@0 25 struct TypedArrayObjectStorage : AllTypedArraysBase {
michael@0 26 protected:
michael@0 27 JSObject* mObj;
michael@0 28
michael@0 29 TypedArrayObjectStorage(JSObject *obj) : mObj(obj)
michael@0 30 {
michael@0 31 }
michael@0 32
michael@0 33 explicit TypedArrayObjectStorage(TypedArrayObjectStorage&& aOther)
michael@0 34 : mObj(aOther.mObj)
michael@0 35 {
michael@0 36 aOther.mObj = nullptr;
michael@0 37 }
michael@0 38
michael@0 39 public:
michael@0 40 inline void TraceSelf(JSTracer* trc)
michael@0 41 {
michael@0 42 if (mObj) {
michael@0 43 JS_CallObjectTracer(trc, &mObj, "TypedArray.mObj");
michael@0 44 }
michael@0 45 }
michael@0 46
michael@0 47 private:
michael@0 48 TypedArrayObjectStorage(const TypedArrayObjectStorage&) MOZ_DELETE;
michael@0 49 };
michael@0 50
michael@0 51 /*
michael@0 52 * Various typed array classes for argument conversion. We have a base class
michael@0 53 * that has a way of initializing a TypedArray from an existing typed array, and
michael@0 54 * a subclass of the base class that supports creation of a relevant typed array
michael@0 55 * or array buffer object.
michael@0 56 */
michael@0 57 template<typename T,
michael@0 58 JSObject* UnwrapArray(JSObject*),
michael@0 59 void GetLengthAndData(JSObject*, uint32_t*, T**)>
michael@0 60 struct TypedArray_base : public TypedArrayObjectStorage {
michael@0 61 typedef T element_type;
michael@0 62
michael@0 63 TypedArray_base(JSObject* obj)
michael@0 64 : TypedArrayObjectStorage(obj),
michael@0 65 mData(nullptr),
michael@0 66 mLength(0),
michael@0 67 mComputed(false)
michael@0 68 {
michael@0 69 MOZ_ASSERT(obj != nullptr);
michael@0 70 }
michael@0 71
michael@0 72 TypedArray_base()
michael@0 73 : TypedArrayObjectStorage(nullptr),
michael@0 74 mData(nullptr),
michael@0 75 mLength(0),
michael@0 76 mComputed(false)
michael@0 77 {
michael@0 78 }
michael@0 79
michael@0 80 explicit TypedArray_base(TypedArray_base&& aOther)
michael@0 81 : TypedArrayObjectStorage(Move(aOther)),
michael@0 82 mData(aOther.mData),
michael@0 83 mLength(aOther.mLength)
michael@0 84 {
michael@0 85 aOther.mData = nullptr;
michael@0 86 aOther.mLength = 0;
michael@0 87 }
michael@0 88
michael@0 89 private:
michael@0 90 mutable T* mData;
michael@0 91 mutable uint32_t mLength;
michael@0 92 mutable bool mComputed;
michael@0 93
michael@0 94 public:
michael@0 95 inline bool Init(JSObject* obj)
michael@0 96 {
michael@0 97 MOZ_ASSERT(!inited());
michael@0 98 DoInit(obj);
michael@0 99 return inited();
michael@0 100 }
michael@0 101
michael@0 102 inline bool inited() const {
michael@0 103 return !!mObj;
michael@0 104 }
michael@0 105
michael@0 106 inline T *Data() const {
michael@0 107 MOZ_ASSERT(mComputed);
michael@0 108 return mData;
michael@0 109 }
michael@0 110
michael@0 111 inline uint32_t Length() const {
michael@0 112 MOZ_ASSERT(mComputed);
michael@0 113 return mLength;
michael@0 114 }
michael@0 115
michael@0 116 inline JSObject *Obj() const {
michael@0 117 MOZ_ASSERT(inited());
michael@0 118 return mObj;
michael@0 119 }
michael@0 120
michael@0 121 inline bool WrapIntoNewCompartment(JSContext* cx)
michael@0 122 {
michael@0 123 return JS_WrapObject(cx,
michael@0 124 JS::MutableHandle<JSObject*>::fromMarkedLocation(&mObj));
michael@0 125 }
michael@0 126
michael@0 127 inline void ComputeLengthAndData() const
michael@0 128 {
michael@0 129 MOZ_ASSERT(inited());
michael@0 130 MOZ_ASSERT(!mComputed);
michael@0 131 GetLengthAndData(mObj, &mLength, &mData);
michael@0 132 mComputed = true;
michael@0 133 }
michael@0 134
michael@0 135 protected:
michael@0 136 inline void DoInit(JSObject* obj)
michael@0 137 {
michael@0 138 mObj = UnwrapArray(obj);
michael@0 139 }
michael@0 140
michael@0 141 inline void ComputeData() const {
michael@0 142 MOZ_ASSERT(inited());
michael@0 143 if (!mComputed) {
michael@0 144 GetLengthAndData(mObj, &mLength, &mData);
michael@0 145 mComputed = true;
michael@0 146 }
michael@0 147 }
michael@0 148
michael@0 149 private:
michael@0 150 TypedArray_base(const TypedArray_base&) MOZ_DELETE;
michael@0 151 };
michael@0 152
michael@0 153
michael@0 154 template<typename T,
michael@0 155 JSObject* UnwrapArray(JSObject*),
michael@0 156 T* GetData(JSObject*),
michael@0 157 void GetLengthAndData(JSObject*, uint32_t*, T**),
michael@0 158 JSObject* CreateNew(JSContext*, uint32_t)>
michael@0 159 struct TypedArray : public TypedArray_base<T, UnwrapArray, GetLengthAndData> {
michael@0 160 TypedArray(JSObject* obj) :
michael@0 161 TypedArray_base<T, UnwrapArray, GetLengthAndData>(obj)
michael@0 162 {}
michael@0 163
michael@0 164 TypedArray() :
michael@0 165 TypedArray_base<T, UnwrapArray, GetLengthAndData>()
michael@0 166 {}
michael@0 167
michael@0 168 explicit TypedArray(TypedArray&& aOther)
michael@0 169 : TypedArray_base<T, UnwrapArray, GetLengthAndData>(Move(aOther))
michael@0 170 {
michael@0 171 }
michael@0 172
michael@0 173 static inline JSObject*
michael@0 174 Create(JSContext* cx, nsWrapperCache* creator, uint32_t length,
michael@0 175 const T* data = nullptr) {
michael@0 176 JS::Rooted<JSObject*> creatorWrapper(cx);
michael@0 177 Maybe<JSAutoCompartment> ac;
michael@0 178 if (creator && (creatorWrapper = creator->GetWrapperPreserveColor())) {
michael@0 179 ac.construct(cx, creatorWrapper);
michael@0 180 }
michael@0 181
michael@0 182 return CreateCommon(cx, length, data);
michael@0 183 }
michael@0 184
michael@0 185 static inline JSObject*
michael@0 186 Create(JSContext* cx, uint32_t length, const T* data = nullptr) {
michael@0 187 return CreateCommon(cx, length, data);
michael@0 188 }
michael@0 189
michael@0 190 private:
michael@0 191 static inline JSObject*
michael@0 192 CreateCommon(JSContext* cx, uint32_t length, const T* data) {
michael@0 193 JSObject* obj = CreateNew(cx, length);
michael@0 194 if (!obj) {
michael@0 195 return nullptr;
michael@0 196 }
michael@0 197 if (data) {
michael@0 198 T* buf = static_cast<T*>(GetData(obj));
michael@0 199 memcpy(buf, data, length*sizeof(T));
michael@0 200 }
michael@0 201 return obj;
michael@0 202 }
michael@0 203
michael@0 204 TypedArray(const TypedArray&) MOZ_DELETE;
michael@0 205 };
michael@0 206
michael@0 207 typedef TypedArray<int8_t, js::UnwrapInt8Array, JS_GetInt8ArrayData,
michael@0 208 js::GetInt8ArrayLengthAndData, JS_NewInt8Array>
michael@0 209 Int8Array;
michael@0 210 typedef TypedArray<uint8_t, js::UnwrapUint8Array, JS_GetUint8ArrayData,
michael@0 211 js::GetUint8ArrayLengthAndData, JS_NewUint8Array>
michael@0 212 Uint8Array;
michael@0 213 typedef TypedArray<uint8_t, js::UnwrapUint8ClampedArray, JS_GetUint8ClampedArrayData,
michael@0 214 js::GetUint8ClampedArrayLengthAndData, JS_NewUint8ClampedArray>
michael@0 215 Uint8ClampedArray;
michael@0 216 typedef TypedArray<int16_t, js::UnwrapInt16Array, JS_GetInt16ArrayData,
michael@0 217 js::GetInt16ArrayLengthAndData, JS_NewInt16Array>
michael@0 218 Int16Array;
michael@0 219 typedef TypedArray<uint16_t, js::UnwrapUint16Array, JS_GetUint16ArrayData,
michael@0 220 js::GetUint16ArrayLengthAndData, JS_NewUint16Array>
michael@0 221 Uint16Array;
michael@0 222 typedef TypedArray<int32_t, js::UnwrapInt32Array, JS_GetInt32ArrayData,
michael@0 223 js::GetInt32ArrayLengthAndData, JS_NewInt32Array>
michael@0 224 Int32Array;
michael@0 225 typedef TypedArray<uint32_t, js::UnwrapUint32Array, JS_GetUint32ArrayData,
michael@0 226 js::GetUint32ArrayLengthAndData, JS_NewUint32Array>
michael@0 227 Uint32Array;
michael@0 228 typedef TypedArray<float, js::UnwrapFloat32Array, JS_GetFloat32ArrayData,
michael@0 229 js::GetFloat32ArrayLengthAndData, JS_NewFloat32Array>
michael@0 230 Float32Array;
michael@0 231 typedef TypedArray<double, js::UnwrapFloat64Array, JS_GetFloat64ArrayData,
michael@0 232 js::GetFloat64ArrayLengthAndData, JS_NewFloat64Array>
michael@0 233 Float64Array;
michael@0 234 typedef TypedArray_base<uint8_t, js::UnwrapArrayBufferView, js::GetArrayBufferViewLengthAndData>
michael@0 235 ArrayBufferView;
michael@0 236 typedef TypedArray<uint8_t, js::UnwrapArrayBuffer, JS_GetArrayBufferData,
michael@0 237 js::GetArrayBufferLengthAndData, JS_NewArrayBuffer>
michael@0 238 ArrayBuffer;
michael@0 239
michael@0 240 // A class for converting an nsTArray to a TypedArray
michael@0 241 // Note: A TypedArrayCreator must not outlive the nsTArray it was created from.
michael@0 242 // So this is best used to pass from things that understand nsTArray to
michael@0 243 // things that understand TypedArray, as with Promise::ArgumentToJSValue.
michael@0 244 template<typename TypedArrayType>
michael@0 245 class TypedArrayCreator
michael@0 246 {
michael@0 247 typedef nsTArray<typename TypedArrayType::element_type> ArrayType;
michael@0 248
michael@0 249 public:
michael@0 250 TypedArrayCreator(const ArrayType& aArray)
michael@0 251 : mArray(aArray)
michael@0 252 {}
michael@0 253
michael@0 254 JSObject* Create(JSContext* aCx) const
michael@0 255 {
michael@0 256 return TypedArrayType::Create(aCx, mArray.Length(), mArray.Elements());
michael@0 257 }
michael@0 258
michael@0 259 private:
michael@0 260 const ArrayType& mArray;
michael@0 261 };
michael@0 262
michael@0 263 // A class for rooting an existing TypedArray struct
michael@0 264 template<typename ArrayType>
michael@0 265 class MOZ_STACK_CLASS TypedArrayRooter : private JS::CustomAutoRooter
michael@0 266 {
michael@0 267 public:
michael@0 268 TypedArrayRooter(JSContext* cx,
michael@0 269 ArrayType* aArray MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
michael@0 270 JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
michael@0 271 mArray(aArray)
michael@0 272 {
michael@0 273 }
michael@0 274
michael@0 275 virtual void trace(JSTracer* trc) MOZ_OVERRIDE
michael@0 276 {
michael@0 277 mArray->TraceSelf(trc);
michael@0 278 }
michael@0 279
michael@0 280 private:
michael@0 281 TypedArrayObjectStorage* const mArray;
michael@0 282 };
michael@0 283
michael@0 284 // And a specialization for dealing with nullable typed arrays
michael@0 285 template<typename Inner> struct Nullable;
michael@0 286 template<typename ArrayType>
michael@0 287 class MOZ_STACK_CLASS TypedArrayRooter<Nullable<ArrayType> > :
michael@0 288 private JS::CustomAutoRooter
michael@0 289 {
michael@0 290 public:
michael@0 291 TypedArrayRooter(JSContext* cx,
michael@0 292 Nullable<ArrayType>* aArray MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
michael@0 293 JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
michael@0 294 mArray(aArray)
michael@0 295 {
michael@0 296 }
michael@0 297
michael@0 298 virtual void trace(JSTracer* trc) MOZ_OVERRIDE
michael@0 299 {
michael@0 300 if (!mArray->IsNull()) {
michael@0 301 mArray->Value().TraceSelf(trc);
michael@0 302 }
michael@0 303 }
michael@0 304
michael@0 305 private:
michael@0 306 Nullable<ArrayType>* const mArray;
michael@0 307 };
michael@0 308
michael@0 309 // Class for easily setting up a rooted typed array object on the stack
michael@0 310 template<typename ArrayType>
michael@0 311 class MOZ_STACK_CLASS RootedTypedArray : public ArrayType,
michael@0 312 private TypedArrayRooter<ArrayType>
michael@0 313 {
michael@0 314 public:
michael@0 315 RootedTypedArray(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
michael@0 316 ArrayType(),
michael@0 317 TypedArrayRooter<ArrayType>(cx,
michael@0 318 MOZ_THIS_IN_INITIALIZER_LIST()
michael@0 319 MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
michael@0 320 {
michael@0 321 }
michael@0 322
michael@0 323 RootedTypedArray(JSContext* cx, JSObject* obj MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
michael@0 324 ArrayType(obj),
michael@0 325 TypedArrayRooter<ArrayType>(cx,
michael@0 326 MOZ_THIS_IN_INITIALIZER_LIST()
michael@0 327 MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
michael@0 328 {
michael@0 329 }
michael@0 330 };
michael@0 331
michael@0 332 } // namespace dom
michael@0 333 } // namespace mozilla
michael@0 334
michael@0 335 #endif /* mozilla_dom_TypedArray_h */

mercurial