Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
michael@0 | 2 | * vim: set ts=8 sts=4 et sw=4 tw=99: |
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 |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #ifndef vm_TypedArrayObject_h |
michael@0 | 8 | #define vm_TypedArrayObject_h |
michael@0 | 9 | |
michael@0 | 10 | #include "jsobj.h" |
michael@0 | 11 | |
michael@0 | 12 | #include "builtin/TypedObject.h" |
michael@0 | 13 | #include "gc/Barrier.h" |
michael@0 | 14 | #include "js/Class.h" |
michael@0 | 15 | #include "vm/ArrayBufferObject.h" |
michael@0 | 16 | |
michael@0 | 17 | typedef struct JSProperty JSProperty; |
michael@0 | 18 | |
michael@0 | 19 | namespace js { |
michael@0 | 20 | |
michael@0 | 21 | /* |
michael@0 | 22 | * TypedArrayObject |
michael@0 | 23 | * |
michael@0 | 24 | * The non-templated base class for the specific typed implementations. |
michael@0 | 25 | * This class holds all the member variables that are used by |
michael@0 | 26 | * the subclasses. |
michael@0 | 27 | */ |
michael@0 | 28 | |
michael@0 | 29 | class TypedArrayObject : public ArrayBufferViewObject |
michael@0 | 30 | { |
michael@0 | 31 | protected: |
michael@0 | 32 | // Typed array properties stored in slots, beyond those shared by all |
michael@0 | 33 | // ArrayBufferViews. |
michael@0 | 34 | static const size_t LENGTH_SLOT = JS_TYPEDOBJ_SLOT_LENGTH; |
michael@0 | 35 | static const size_t TYPE_SLOT = JS_TYPEDOBJ_SLOT_TYPE_DESCR; |
michael@0 | 36 | static const size_t RESERVED_SLOTS = JS_TYPEDOBJ_SLOTS; |
michael@0 | 37 | static const size_t DATA_SLOT = JS_TYPEDOBJ_SLOT_DATA; |
michael@0 | 38 | |
michael@0 | 39 | static_assert(js::detail::TypedArrayLengthSlot == LENGTH_SLOT, |
michael@0 | 40 | "bad inlined constant in jsfriendapi.h"); |
michael@0 | 41 | |
michael@0 | 42 | public: |
michael@0 | 43 | static const Class classes[ScalarTypeDescr::TYPE_MAX]; |
michael@0 | 44 | static const Class protoClasses[ScalarTypeDescr::TYPE_MAX]; |
michael@0 | 45 | |
michael@0 | 46 | static const size_t FIXED_DATA_START = DATA_SLOT + 1; |
michael@0 | 47 | |
michael@0 | 48 | // For typed arrays which can store their data inline, the array buffer |
michael@0 | 49 | // object is created lazily. |
michael@0 | 50 | static const uint32_t INLINE_BUFFER_LIMIT = |
michael@0 | 51 | (JSObject::MAX_FIXED_SLOTS - FIXED_DATA_START) * sizeof(Value); |
michael@0 | 52 | |
michael@0 | 53 | static gc::AllocKind |
michael@0 | 54 | AllocKindForLazyBuffer(size_t nbytes) |
michael@0 | 55 | { |
michael@0 | 56 | JS_ASSERT(nbytes <= INLINE_BUFFER_LIMIT); |
michael@0 | 57 | /* For GGC we need at least one slot in which to store a forwarding pointer. */ |
michael@0 | 58 | size_t dataSlots = Max(size_t(1), AlignBytes(nbytes, sizeof(Value)) / sizeof(Value)); |
michael@0 | 59 | JS_ASSERT(nbytes <= dataSlots * sizeof(Value)); |
michael@0 | 60 | return gc::GetGCObjectKind(FIXED_DATA_START + dataSlots); |
michael@0 | 61 | } |
michael@0 | 62 | |
michael@0 | 63 | static Value bufferValue(TypedArrayObject *tarr) { |
michael@0 | 64 | return tarr->getFixedSlot(BUFFER_SLOT); |
michael@0 | 65 | } |
michael@0 | 66 | static Value byteOffsetValue(TypedArrayObject *tarr) { |
michael@0 | 67 | return tarr->getFixedSlot(BYTEOFFSET_SLOT); |
michael@0 | 68 | } |
michael@0 | 69 | static Value byteLengthValue(TypedArrayObject *tarr) { |
michael@0 | 70 | return tarr->getFixedSlot(BYTELENGTH_SLOT); |
michael@0 | 71 | } |
michael@0 | 72 | static Value lengthValue(TypedArrayObject *tarr) { |
michael@0 | 73 | return tarr->getFixedSlot(LENGTH_SLOT); |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | static bool |
michael@0 | 77 | ensureHasBuffer(JSContext *cx, Handle<TypedArrayObject *> tarray); |
michael@0 | 78 | |
michael@0 | 79 | ArrayBufferObject *sharedBuffer() const; |
michael@0 | 80 | ArrayBufferObject *buffer() const { |
michael@0 | 81 | JSObject *obj = bufferValue(const_cast<TypedArrayObject*>(this)).toObjectOrNull(); |
michael@0 | 82 | if (!obj) |
michael@0 | 83 | return nullptr; |
michael@0 | 84 | if (obj->is<ArrayBufferObject>()) |
michael@0 | 85 | return &obj->as<ArrayBufferObject>(); |
michael@0 | 86 | return sharedBuffer(); |
michael@0 | 87 | } |
michael@0 | 88 | uint32_t byteOffset() const { |
michael@0 | 89 | return byteOffsetValue(const_cast<TypedArrayObject*>(this)).toInt32(); |
michael@0 | 90 | } |
michael@0 | 91 | uint32_t byteLength() const { |
michael@0 | 92 | return byteLengthValue(const_cast<TypedArrayObject*>(this)).toInt32(); |
michael@0 | 93 | } |
michael@0 | 94 | uint32_t length() const { |
michael@0 | 95 | return lengthValue(const_cast<TypedArrayObject*>(this)).toInt32(); |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | uint32_t type() const { |
michael@0 | 99 | return getFixedSlot(TYPE_SLOT).toInt32(); |
michael@0 | 100 | } |
michael@0 | 101 | void *viewData() const { |
michael@0 | 102 | // Keep synced with js::Get<Type>ArrayLengthAndData in jsfriendapi.h! |
michael@0 | 103 | return static_cast<void*>(getPrivate(DATA_SLOT)); |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | Value getElement(uint32_t index); |
michael@0 | 107 | static void setElement(TypedArrayObject &obj, uint32_t index, double d); |
michael@0 | 108 | |
michael@0 | 109 | void neuter(void *newData); |
michael@0 | 110 | |
michael@0 | 111 | static uint32_t slotWidth(int atype) { |
michael@0 | 112 | switch (atype) { |
michael@0 | 113 | case ScalarTypeDescr::TYPE_INT8: |
michael@0 | 114 | case ScalarTypeDescr::TYPE_UINT8: |
michael@0 | 115 | case ScalarTypeDescr::TYPE_UINT8_CLAMPED: |
michael@0 | 116 | return 1; |
michael@0 | 117 | case ScalarTypeDescr::TYPE_INT16: |
michael@0 | 118 | case ScalarTypeDescr::TYPE_UINT16: |
michael@0 | 119 | return 2; |
michael@0 | 120 | case ScalarTypeDescr::TYPE_INT32: |
michael@0 | 121 | case ScalarTypeDescr::TYPE_UINT32: |
michael@0 | 122 | case ScalarTypeDescr::TYPE_FLOAT32: |
michael@0 | 123 | return 4; |
michael@0 | 124 | case ScalarTypeDescr::TYPE_FLOAT64: |
michael@0 | 125 | return 8; |
michael@0 | 126 | default: |
michael@0 | 127 | MOZ_ASSUME_UNREACHABLE("invalid typed array type"); |
michael@0 | 128 | } |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | int slotWidth() { |
michael@0 | 132 | return slotWidth(type()); |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | /* |
michael@0 | 136 | * Byte length above which created typed arrays and data views will have |
michael@0 | 137 | * singleton types regardless of the context in which they are created. |
michael@0 | 138 | */ |
michael@0 | 139 | static const uint32_t SINGLETON_TYPE_BYTE_LENGTH = 1024 * 1024 * 10; |
michael@0 | 140 | |
michael@0 | 141 | static int lengthOffset(); |
michael@0 | 142 | static int dataOffset(); |
michael@0 | 143 | }; |
michael@0 | 144 | |
michael@0 | 145 | inline bool |
michael@0 | 146 | IsTypedArrayClass(const Class *clasp) |
michael@0 | 147 | { |
michael@0 | 148 | return &TypedArrayObject::classes[0] <= clasp && |
michael@0 | 149 | clasp < &TypedArrayObject::classes[ScalarTypeDescr::TYPE_MAX]; |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | inline bool |
michael@0 | 153 | IsTypedArrayProtoClass(const Class *clasp) |
michael@0 | 154 | { |
michael@0 | 155 | return &TypedArrayObject::protoClasses[0] <= clasp && |
michael@0 | 156 | clasp < &TypedArrayObject::protoClasses[ScalarTypeDescr::TYPE_MAX]; |
michael@0 | 157 | } |
michael@0 | 158 | |
michael@0 | 159 | bool |
michael@0 | 160 | IsTypedArrayConstructor(HandleValue v, uint32_t type); |
michael@0 | 161 | |
michael@0 | 162 | bool |
michael@0 | 163 | IsTypedArrayBuffer(HandleValue v); |
michael@0 | 164 | |
michael@0 | 165 | ArrayBufferObject & |
michael@0 | 166 | AsTypedArrayBuffer(HandleValue v); |
michael@0 | 167 | |
michael@0 | 168 | // Return value is whether the string is some integer. If the string is an |
michael@0 | 169 | // integer which is not representable as a uint64_t, the return value is true |
michael@0 | 170 | // and the resulting index is UINT64_MAX. |
michael@0 | 171 | bool |
michael@0 | 172 | StringIsTypedArrayIndex(JSLinearString *str, uint64_t *indexp); |
michael@0 | 173 | |
michael@0 | 174 | inline bool |
michael@0 | 175 | IsTypedArrayIndex(jsid id, uint64_t *indexp) |
michael@0 | 176 | { |
michael@0 | 177 | if (JSID_IS_INT(id)) { |
michael@0 | 178 | int32_t i = JSID_TO_INT(id); |
michael@0 | 179 | JS_ASSERT(i >= 0); |
michael@0 | 180 | *indexp = (double)i; |
michael@0 | 181 | return true; |
michael@0 | 182 | } |
michael@0 | 183 | |
michael@0 | 184 | if (MOZ_UNLIKELY(!JSID_IS_STRING(id))) |
michael@0 | 185 | return false; |
michael@0 | 186 | |
michael@0 | 187 | JSAtom *atom = JSID_TO_ATOM(id); |
michael@0 | 188 | |
michael@0 | 189 | jschar c = atom->chars()[0]; |
michael@0 | 190 | if (!JS7_ISDEC(c) && c != '-') |
michael@0 | 191 | return false; |
michael@0 | 192 | |
michael@0 | 193 | return StringIsTypedArrayIndex(atom, indexp); |
michael@0 | 194 | } |
michael@0 | 195 | |
michael@0 | 196 | static inline unsigned |
michael@0 | 197 | TypedArrayShift(ArrayBufferView::ViewType viewType) |
michael@0 | 198 | { |
michael@0 | 199 | switch (viewType) { |
michael@0 | 200 | case ArrayBufferView::TYPE_INT8: |
michael@0 | 201 | case ArrayBufferView::TYPE_UINT8: |
michael@0 | 202 | case ArrayBufferView::TYPE_UINT8_CLAMPED: |
michael@0 | 203 | return 0; |
michael@0 | 204 | case ArrayBufferView::TYPE_INT16: |
michael@0 | 205 | case ArrayBufferView::TYPE_UINT16: |
michael@0 | 206 | return 1; |
michael@0 | 207 | case ArrayBufferView::TYPE_INT32: |
michael@0 | 208 | case ArrayBufferView::TYPE_UINT32: |
michael@0 | 209 | case ArrayBufferView::TYPE_FLOAT32: |
michael@0 | 210 | return 2; |
michael@0 | 211 | case ArrayBufferView::TYPE_FLOAT64: |
michael@0 | 212 | return 3; |
michael@0 | 213 | default:; |
michael@0 | 214 | } |
michael@0 | 215 | MOZ_ASSUME_UNREACHABLE("Unexpected array type"); |
michael@0 | 216 | } |
michael@0 | 217 | |
michael@0 | 218 | class DataViewObject : public ArrayBufferViewObject |
michael@0 | 219 | { |
michael@0 | 220 | static const size_t RESERVED_SLOTS = JS_DATAVIEW_SLOTS; |
michael@0 | 221 | static const size_t DATA_SLOT = JS_TYPEDOBJ_SLOT_DATA; |
michael@0 | 222 | |
michael@0 | 223 | private: |
michael@0 | 224 | static const Class protoClass; |
michael@0 | 225 | |
michael@0 | 226 | static bool is(HandleValue v) { |
michael@0 | 227 | return v.isObject() && v.toObject().hasClass(&class_); |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | template <typename NativeType> |
michael@0 | 231 | static uint8_t * |
michael@0 | 232 | getDataPointer(JSContext *cx, Handle<DataViewObject*> obj, uint32_t offset); |
michael@0 | 233 | |
michael@0 | 234 | template<Value ValueGetter(DataViewObject *view)> |
michael@0 | 235 | static bool |
michael@0 | 236 | getterImpl(JSContext *cx, CallArgs args); |
michael@0 | 237 | |
michael@0 | 238 | template<Value ValueGetter(DataViewObject *view)> |
michael@0 | 239 | static bool |
michael@0 | 240 | getter(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 241 | |
michael@0 | 242 | template<Value ValueGetter(DataViewObject *view)> |
michael@0 | 243 | static bool |
michael@0 | 244 | defineGetter(JSContext *cx, PropertyName *name, HandleObject proto); |
michael@0 | 245 | |
michael@0 | 246 | public: |
michael@0 | 247 | static const Class class_; |
michael@0 | 248 | |
michael@0 | 249 | static Value byteOffsetValue(DataViewObject *view) { |
michael@0 | 250 | Value v = view->getReservedSlot(BYTEOFFSET_SLOT); |
michael@0 | 251 | JS_ASSERT(v.toInt32() >= 0); |
michael@0 | 252 | return v; |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | static Value byteLengthValue(DataViewObject *view) { |
michael@0 | 256 | Value v = view->getReservedSlot(BYTELENGTH_SLOT); |
michael@0 | 257 | JS_ASSERT(v.toInt32() >= 0); |
michael@0 | 258 | return v; |
michael@0 | 259 | } |
michael@0 | 260 | |
michael@0 | 261 | static Value bufferValue(DataViewObject *view) { |
michael@0 | 262 | return view->getReservedSlot(BUFFER_SLOT); |
michael@0 | 263 | } |
michael@0 | 264 | |
michael@0 | 265 | uint32_t byteOffset() const { |
michael@0 | 266 | return byteOffsetValue(const_cast<DataViewObject*>(this)).toInt32(); |
michael@0 | 267 | } |
michael@0 | 268 | |
michael@0 | 269 | uint32_t byteLength() const { |
michael@0 | 270 | return byteLengthValue(const_cast<DataViewObject*>(this)).toInt32(); |
michael@0 | 271 | } |
michael@0 | 272 | |
michael@0 | 273 | ArrayBufferObject &arrayBuffer() const { |
michael@0 | 274 | return bufferValue(const_cast<DataViewObject*>(this)).toObject().as<ArrayBufferObject>(); |
michael@0 | 275 | } |
michael@0 | 276 | |
michael@0 | 277 | void *dataPointer() const { |
michael@0 | 278 | return getPrivate(); |
michael@0 | 279 | } |
michael@0 | 280 | |
michael@0 | 281 | static bool class_constructor(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 282 | static bool constructWithProto(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 283 | static bool construct(JSContext *cx, JSObject *bufobj, const CallArgs &args, |
michael@0 | 284 | HandleObject proto); |
michael@0 | 285 | |
michael@0 | 286 | static inline DataViewObject * |
michael@0 | 287 | create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength, |
michael@0 | 288 | Handle<ArrayBufferObject*> arrayBuffer, JSObject *proto); |
michael@0 | 289 | |
michael@0 | 290 | static bool getInt8Impl(JSContext *cx, CallArgs args); |
michael@0 | 291 | static bool fun_getInt8(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 292 | |
michael@0 | 293 | static bool getUint8Impl(JSContext *cx, CallArgs args); |
michael@0 | 294 | static bool fun_getUint8(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 295 | |
michael@0 | 296 | static bool getInt16Impl(JSContext *cx, CallArgs args); |
michael@0 | 297 | static bool fun_getInt16(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 298 | |
michael@0 | 299 | static bool getUint16Impl(JSContext *cx, CallArgs args); |
michael@0 | 300 | static bool fun_getUint16(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 301 | |
michael@0 | 302 | static bool getInt32Impl(JSContext *cx, CallArgs args); |
michael@0 | 303 | static bool fun_getInt32(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 304 | |
michael@0 | 305 | static bool getUint32Impl(JSContext *cx, CallArgs args); |
michael@0 | 306 | static bool fun_getUint32(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 307 | |
michael@0 | 308 | static bool getFloat32Impl(JSContext *cx, CallArgs args); |
michael@0 | 309 | static bool fun_getFloat32(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 310 | |
michael@0 | 311 | static bool getFloat64Impl(JSContext *cx, CallArgs args); |
michael@0 | 312 | static bool fun_getFloat64(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 313 | |
michael@0 | 314 | static bool setInt8Impl(JSContext *cx, CallArgs args); |
michael@0 | 315 | static bool fun_setInt8(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 316 | |
michael@0 | 317 | static bool setUint8Impl(JSContext *cx, CallArgs args); |
michael@0 | 318 | static bool fun_setUint8(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 319 | |
michael@0 | 320 | static bool setInt16Impl(JSContext *cx, CallArgs args); |
michael@0 | 321 | static bool fun_setInt16(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 322 | |
michael@0 | 323 | static bool setUint16Impl(JSContext *cx, CallArgs args); |
michael@0 | 324 | static bool fun_setUint16(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 325 | |
michael@0 | 326 | static bool setInt32Impl(JSContext *cx, CallArgs args); |
michael@0 | 327 | static bool fun_setInt32(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 328 | |
michael@0 | 329 | static bool setUint32Impl(JSContext *cx, CallArgs args); |
michael@0 | 330 | static bool fun_setUint32(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 331 | |
michael@0 | 332 | static bool setFloat32Impl(JSContext *cx, CallArgs args); |
michael@0 | 333 | static bool fun_setFloat32(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 334 | |
michael@0 | 335 | static bool setFloat64Impl(JSContext *cx, CallArgs args); |
michael@0 | 336 | static bool fun_setFloat64(JSContext *cx, unsigned argc, Value *vp); |
michael@0 | 337 | |
michael@0 | 338 | static bool initClass(JSContext *cx); |
michael@0 | 339 | static void neuter(JSObject *view); |
michael@0 | 340 | template<typename NativeType> |
michael@0 | 341 | static bool read(JSContext *cx, Handle<DataViewObject*> obj, |
michael@0 | 342 | CallArgs &args, NativeType *val, const char *method); |
michael@0 | 343 | template<typename NativeType> |
michael@0 | 344 | static bool write(JSContext *cx, Handle<DataViewObject*> obj, |
michael@0 | 345 | CallArgs &args, const char *method); |
michael@0 | 346 | |
michael@0 | 347 | void neuter(void *newData); |
michael@0 | 348 | |
michael@0 | 349 | private: |
michael@0 | 350 | static const JSFunctionSpec jsfuncs[]; |
michael@0 | 351 | }; |
michael@0 | 352 | |
michael@0 | 353 | static inline int32_t |
michael@0 | 354 | ClampIntForUint8Array(int32_t x) |
michael@0 | 355 | { |
michael@0 | 356 | if (x < 0) |
michael@0 | 357 | return 0; |
michael@0 | 358 | if (x > 255) |
michael@0 | 359 | return 255; |
michael@0 | 360 | return x; |
michael@0 | 361 | } |
michael@0 | 362 | |
michael@0 | 363 | } // namespace js |
michael@0 | 364 | |
michael@0 | 365 | template <> |
michael@0 | 366 | inline bool |
michael@0 | 367 | JSObject::is<js::TypedArrayObject>() const |
michael@0 | 368 | { |
michael@0 | 369 | return js::IsTypedArrayClass(getClass()); |
michael@0 | 370 | } |
michael@0 | 371 | |
michael@0 | 372 | template <> |
michael@0 | 373 | inline bool |
michael@0 | 374 | JSObject::is<js::ArrayBufferViewObject>() const |
michael@0 | 375 | { |
michael@0 | 376 | return is<js::DataViewObject>() || is<js::TypedArrayObject>() || |
michael@0 | 377 | IsTypedObjectClass(getClass()); |
michael@0 | 378 | } |
michael@0 | 379 | |
michael@0 | 380 | #endif /* vm_TypedArrayObject_h */ |