/* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil -*- */ /* vim: set ts=40 sw=4 et tw=99: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jstypedarray_h #define jstypedarray_h #include "jsapi.h" #include "jsclass.h" #include "jsobj.h" #include "gc/Barrier.h" typedef struct JSProperty JSProperty; namespace js { /* * ArrayBufferObject * * This class holds the underlying raw buffer that the various ArrayBufferView * subclasses (DataView and the TypedArrays) access. It can be created * explicitly and passed to an ArrayBufferView subclass, or can be created * implicitly by constructing a TypedArray with a size. */ class ArrayBufferObject : public JSObject { public: static Class protoClass; static JSPropertySpec jsprops[]; static JSFunctionSpec jsfuncs[]; static JSBool prop_getByteLength(JSContext *cx, HandleObject obj, HandleId id, Value *vp); static JSBool fun_slice(JSContext *cx, unsigned argc, Value *vp); static JSBool class_constructor(JSContext *cx, unsigned argc, Value *vp); static JSObject *create(JSContext *cx, uint32_t nbytes, uint8_t *contents = NULL); static JSObject *createSlice(JSContext *cx, ArrayBufferObject &arrayBuffer, uint32_t begin, uint32_t end); static void obj_trace(JSTracer *trc, JSObject *obj); static JSBool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, JSObject **objp, JSProperty **propp); static JSBool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, JSObject **objp, JSProperty **propp); static JSBool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, JSObject **objp, JSProperty **propp); static JSBool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, JSObject **objp, JSProperty **propp); static JSBool obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, const Value *v, PropertyOp getter, StrictPropertyOp setter, unsigned attrs); static JSBool obj_defineProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *v, PropertyOp getter, StrictPropertyOp setter, unsigned attrs); static JSBool obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, const Value *v, PropertyOp getter, StrictPropertyOp setter, unsigned attrs); static JSBool obj_defineSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *v, PropertyOp getter, StrictPropertyOp setter, unsigned attrs); static JSBool obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp); static JSBool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, Value *vp); static JSBool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp); static JSBool obj_getElementIfPresent(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp, bool *present); static JSBool obj_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp); static JSBool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict); static JSBool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict); static JSBool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict); static JSBool obj_setSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict); static JSBool obj_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp); static JSBool obj_getPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp); static JSBool obj_getElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp); static JSBool obj_getSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp); static JSBool obj_setGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp); static JSBool obj_setPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp); static JSBool obj_setElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp); static JSBool obj_setSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp); static JSBool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *rval, JSBool strict); static JSBool obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index, Value *rval, JSBool strict); static JSBool obj_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *rval, JSBool strict); static JSBool obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op, Value *statep, jsid *idp); static JSType obj_typeOf(JSContext *cx, HandleObject obj); bool allocateSlots(JSContext *cx, uint32_t size, uint8_t *contents = NULL); inline uint32_t byteLength() const; inline uint8_t * dataPointer() const; /* * Check if the arrayBuffer contains any data. This will return false for * ArrayBuffer.prototype and neutered ArrayBuffers. */ inline bool hasData() const; }; /* * TypedArray * * The non-templated base class for the specific typed implementations. * This class holds all the member variables that are used by * the subclasses. */ struct TypedArray { enum { TYPE_INT8 = 0, TYPE_UINT8, TYPE_INT16, TYPE_UINT16, TYPE_INT32, TYPE_UINT32, TYPE_FLOAT32, TYPE_FLOAT64, /* * Special type that's a uint8, but assignments are clamped to 0 .. 255. * Treat the raw data type as a uint8. */ TYPE_UINT8_CLAMPED, TYPE_MAX }; enum { /* Properties of the typed array stored in reserved slots. */ FIELD_LENGTH = 0, FIELD_BYTEOFFSET, FIELD_BYTELENGTH, FIELD_TYPE, FIELD_BUFFER, FIELD_MAX, NUM_FIXED_SLOTS = 7 }; // and MUST NOT be used to construct new objects. static Class classes[TYPE_MAX]; // These are the proto/original classes, used // fo constructing new objects static Class protoClasses[TYPE_MAX]; static JSPropertySpec jsprops[]; static JSBool prop_getBuffer(JSContext *cx, HandleObject obj, HandleId id, Value *vp); static JSBool prop_getByteOffset(JSContext *cx, HandleObject obj, HandleId id, Value *vp); static JSBool prop_getByteLength(JSContext *cx, HandleObject obj, HandleId id, Value *vp); static JSBool prop_getLength(JSContext *cx, HandleObject obj, HandleId id, Value *vp); static JSBool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id, JSObject **objp, JSProperty **propp); static JSBool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, JSObject **objp, JSProperty **propp); static JSBool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index, JSObject **objp, JSProperty **propp); static JSBool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, JSObject **objp, JSProperty **propp); static JSBool obj_getGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp); static JSBool obj_getPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp); static JSBool obj_getElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp); static JSBool obj_getSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp); static JSBool obj_setGenericAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp); static JSBool obj_setPropertyAttributes(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp); static JSBool obj_setElementAttributes(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp); static JSBool obj_setSpecialAttributes(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp); static uint32_t getLength(JSObject *obj); static uint32_t getByteOffset(JSObject *obj); static uint32_t getByteLength(JSObject *obj); static uint32_t getType(JSObject *obj); static ArrayBufferObject * getBuffer(JSObject *obj); static void * getDataOffset(JSObject *obj); public: static bool isArrayIndex(JSContext *cx, JSObject *obj, jsid id, uint32_t *ip = NULL); static inline uint32_t slotWidth(int atype) { switch (atype) { case js::TypedArray::TYPE_INT8: case js::TypedArray::TYPE_UINT8: case js::TypedArray::TYPE_UINT8_CLAMPED: return 1; case js::TypedArray::TYPE_INT16: case js::TypedArray::TYPE_UINT16: return 2; case js::TypedArray::TYPE_INT32: case js::TypedArray::TYPE_UINT32: case js::TypedArray::TYPE_FLOAT32: return 4; case js::TypedArray::TYPE_FLOAT64: return 8; default: JS_NOT_REACHED("invalid typed array type"); return 0; } } static inline int slotWidth(JSObject *obj) { return slotWidth(getType(obj)); } static int lengthOffset(); static int dataOffset(); }; inline bool IsTypedArrayClass(const Class *clasp) { return &TypedArray::classes[0] <= clasp && clasp < &TypedArray::classes[TypedArray::TYPE_MAX]; } inline bool IsTypedArrayProtoClass(const Class *clasp) { return &TypedArray::protoClasses[0] <= clasp && clasp < &TypedArray::protoClasses[TypedArray::TYPE_MAX]; } inline bool IsTypedArray(JSObject *obj) { return IsTypedArrayClass(obj->getClass()); } inline bool IsTypedArrayProto(JSObject *obj) { return IsTypedArrayProtoClass(obj->getClass()); } class DataViewObject : public JSObject { static Class protoClass; static const size_t BYTEOFFSET_SLOT = 0; static const size_t BYTELENGTH_SLOT = 1; static const size_t BUFFER_SLOT = 2; public: static const size_t RESERVED_SLOTS = 3; static JSBool prop_getBuffer(JSContext *cx, HandleObject obj, HandleId id, Value *vp); static JSBool prop_getByteOffset(JSContext *cx, HandleObject obj, HandleId id, Value *vp); static JSBool prop_getByteLength(JSContext *cx, HandleObject obj, HandleId id, Value *vp); static JSBool class_constructor(JSContext *cx, unsigned argc, Value *vp); static JSBool constructWithProto(JSContext *cx, unsigned argc, Value *vp); static JSBool construct(JSContext *cx, JSObject *bufobj, const CallArgs &args, JSObject *proto); static inline DataViewObject * create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength, Handle arrayBuffer, JSObject *proto); static JSBool fun_getInt8(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_getUint8(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_getInt16(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_getUint16(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_getInt32(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_getUint32(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_getFloat32(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_getFloat64(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_setInt8(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_setUint8(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_setInt16(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_setUint16(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_setInt32(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_setUint32(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_setFloat32(JSContext *cx, unsigned argc, Value *vp); static JSBool fun_setFloat64(JSContext *cx, unsigned argc, Value *vp); inline uint32_t byteLength(); inline uint32_t byteOffset(); inline JSObject & arrayBuffer(); inline void *dataPointer(); inline bool hasBuffer() const; static JSObject *initClass(JSContext *cx, GlobalObject *global); bool getDataPointer(JSContext *cx, CallArgs args, size_t typeSize, uint8_t **data); template bool read(JSContext *cx, CallArgs &args, NativeType *val, const char *method); template bool write(JSContext *cx, CallArgs &args, const char *method); private: static JSPropertySpec jsprops[]; static JSFunctionSpec jsfuncs[]; }; bool IsDataView(JSObject *obj); } // namespace js #endif /* jstypedarray_h */