mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 741039 - Modify TypedArrays and ArrayBuffers to comply with the WebIDL spec. r=Waldo
WebIDL 4.4.6 says Float32Array.prototype is not a platform object and should throw TypeErrors when any of the Float32Array attributes is accessed. This patch makes obj->isTypedArray only succeed for actual TypedArray instances, and adds TypeErrors when special properties are retrieved from the prototypes. This patch also eliminates some lingering uses of TypedArray::getTypedArray and makes it and getArrayBuffer static within jstypedarray.cpp. (Both are used for objects whose prototypes are typed arrays or array buffers.) --HG-- extra : rebase_source : 93032b5c8dc98c4e18eec4fa438f6a9a4173487d
This commit is contained in:
parent
3250e70d87
commit
7aee790f0d
@ -1741,7 +1741,7 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define CLASP(name) (&name##Class)
|
#define CLASP(name) (&name##Class)
|
||||||
#define TYPED_ARRAY_CLASP(type) (&TypedArray::fastClasses[TypedArray::type])
|
#define TYPED_ARRAY_CLASP(type) (&TypedArray::classes[TypedArray::type])
|
||||||
#define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
|
#define EAGER_ATOM(name) ATOM_OFFSET(name), NULL
|
||||||
#define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
|
#define EAGER_CLASS_ATOM(name) CLASS_ATOM_OFFSET(name), NULL
|
||||||
#define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
|
#define EAGER_ATOM_AND_CLASP(name) EAGER_CLASS_ATOM(name), CLASP(name)
|
||||||
|
@ -434,9 +434,8 @@ JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSStructuredCloneWriter::writeTypedArray(JSObject *obj)
|
JSStructuredCloneWriter::writeTypedArray(JSObject *arr)
|
||||||
{
|
{
|
||||||
JSObject *arr = TypedArray::getTypedArray(obj);
|
|
||||||
if (!out.writePair(ArrayTypeToTag(TypedArray::getType(arr)), TypedArray::getLength(arr)))
|
if (!out.writePair(ArrayTypeToTag(TypedArray::getType(arr)), TypedArray::getLength(arr)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -750,27 +749,26 @@ JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp
|
|||||||
return false;
|
return false;
|
||||||
vp->setObject(*obj);
|
vp->setObject(*obj);
|
||||||
|
|
||||||
JSObject *arr = TypedArray::getTypedArray(obj);
|
JS_ASSERT(TypedArray::getLength(obj) == nelems);
|
||||||
JS_ASSERT(TypedArray::getLength(arr) == nelems);
|
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case SCTAG_TYPED_ARRAY_INT8:
|
case SCTAG_TYPED_ARRAY_INT8:
|
||||||
return in.readArray((uint8_t *) JS_GetInt8ArrayData(arr, context()), nelems);
|
return in.readArray((uint8_t*) JS_GetInt8ArrayData(obj, context()), nelems);
|
||||||
case SCTAG_TYPED_ARRAY_UINT8:
|
case SCTAG_TYPED_ARRAY_UINT8:
|
||||||
return in.readArray((uint8_t *) JS_GetUint8ArrayData(arr, context()), nelems);
|
return in.readArray(JS_GetUint8ArrayData(obj, context()), nelems);
|
||||||
case SCTAG_TYPED_ARRAY_INT16:
|
case SCTAG_TYPED_ARRAY_INT16:
|
||||||
return in.readArray((uint16_t *) JS_GetInt16ArrayData(arr, context()), nelems);
|
return in.readArray((uint16_t*) JS_GetInt16ArrayData(obj, context()), nelems);
|
||||||
case SCTAG_TYPED_ARRAY_UINT16:
|
case SCTAG_TYPED_ARRAY_UINT16:
|
||||||
return in.readArray((uint16_t *) JS_GetUint16ArrayData(arr, context()), nelems);
|
return in.readArray(JS_GetUint16ArrayData(obj, context()), nelems);
|
||||||
case SCTAG_TYPED_ARRAY_INT32:
|
case SCTAG_TYPED_ARRAY_INT32:
|
||||||
return in.readArray((uint32_t *) JS_GetInt32ArrayData(arr, context()), nelems);
|
return in.readArray((uint32_t*) JS_GetInt32ArrayData(obj, context()), nelems);
|
||||||
case SCTAG_TYPED_ARRAY_UINT32:
|
case SCTAG_TYPED_ARRAY_UINT32:
|
||||||
return in.readArray((uint32_t *) JS_GetUint32ArrayData(arr, context()), nelems);
|
return in.readArray(JS_GetUint32ArrayData(obj, context()), nelems);
|
||||||
case SCTAG_TYPED_ARRAY_FLOAT32:
|
case SCTAG_TYPED_ARRAY_FLOAT32:
|
||||||
return in.readArray((uint32_t *) JS_GetFloat32ArrayData(arr, context()), nelems);
|
return in.readArray((uint32_t*) JS_GetFloat32ArrayData(obj, context()), nelems);
|
||||||
case SCTAG_TYPED_ARRAY_FLOAT64:
|
case SCTAG_TYPED_ARRAY_FLOAT64:
|
||||||
return in.readArray((uint64_t *) JS_GetFloat64ArrayData(arr, context()), nelems);
|
return in.readArray((uint64_t*) JS_GetFloat64ArrayData(obj, context()), nelems);
|
||||||
case SCTAG_TYPED_ARRAY_UINT8_CLAMPED:
|
case SCTAG_TYPED_ARRAY_UINT8_CLAMPED:
|
||||||
return in.readArray((uint8_t *) JS_GetUint8ClampedArrayData(arr, context()), nelems);
|
return in.readArray(JS_GetUint8ClampedArrayData(obj, context()), nelems);
|
||||||
default:
|
default:
|
||||||
JS_NOT_REACHED("unknown TypedArray type");
|
JS_NOT_REACHED("unknown TypedArray type");
|
||||||
return false;
|
return false;
|
||||||
|
@ -233,8 +233,7 @@ GetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, Value *vp
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (obj->isTypedArray()) {
|
if (obj->isTypedArray()) {
|
||||||
JSObject *tarray = TypedArray::getTypedArray(obj);
|
*vp = Int32Value(TypedArray::getLength(obj));
|
||||||
*vp = Int32Value(TypedArray::getLength(tarray));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -811,7 +811,7 @@ inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
|
|||||||
inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
|
inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
|
||||||
inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
|
inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
|
||||||
inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
|
inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
|
||||||
inline bool JSObject::isTypedArray() const { return IsFastTypedArrayClass(getClass()); }
|
inline bool JSObject::isTypedArray() const { return IsTypedArrayClass(getClass()); }
|
||||||
inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
|
inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
|
||||||
inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
|
inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
|
||||||
inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
|
inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
|
||||||
|
@ -138,29 +138,27 @@ ToClampedIndex(JSContext *cx, const Value &v, int32_t length, int32_t *out)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walks up the prototype chain to find the actual ArrayBuffer data.
|
* Walks up the prototype chain to find the actual ArrayBuffer data, if any.
|
||||||
* This MAY return NULL. Callers should always use isArrayBuffer()
|
|
||||||
* first.
|
|
||||||
*/
|
*/
|
||||||
JSObject *
|
static ArrayBufferObject *
|
||||||
ArrayBufferObject::getArrayBuffer(JSObject *obj)
|
getArrayBuffer(JSObject *obj)
|
||||||
{
|
{
|
||||||
while (obj && !obj->isArrayBuffer())
|
while (obj && !obj->isArrayBuffer())
|
||||||
obj = obj->getProto();
|
obj = obj->getProto();
|
||||||
return obj;
|
return obj ? &obj->asArrayBuffer() : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
ArrayBufferObject::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
ArrayBufferObject::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||||
{
|
{
|
||||||
JSObject *bufobj = getArrayBuffer(obj);
|
ArrayBufferObject *buffer = getArrayBuffer(obj);
|
||||||
if (!bufobj) {
|
if (!buffer) {
|
||||||
vp->setInt32(0);
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||||
return true;
|
JSMSG_INCOMPATIBLE_PROTO, "ArrayBuffer", "byteLength", "object");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayBufferObject &arrayBuffer = bufobj->asArrayBuffer();
|
vp->setInt32(int32_t(buffer->byteLength()));
|
||||||
vp->setInt32(int32_t(arrayBuffer.byteLength()));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +503,15 @@ ArrayBufferObject::obj_getProperty(JSContext *cx, JSObject *obj_,
|
|||||||
RootedVarObject obj(cx, obj_), receiver(cx, receiver_);
|
RootedVarObject obj(cx, obj_), receiver(cx, receiver_);
|
||||||
RootedVarPropertyName name(cx, name_);
|
RootedVarPropertyName name(cx, name_);
|
||||||
|
|
||||||
obj = getArrayBuffer(obj);
|
if (!(obj = getArrayBuffer(obj))) {
|
||||||
|
JSAutoByteString bs(cx, name);
|
||||||
|
if (!bs)
|
||||||
|
return false;
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||||
|
JSMSG_INCOMPATIBLE_PROTO, "ArrayBuffer", bs.ptr(), "object");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (name == cx->runtime->atomState.byteLengthAtom) {
|
if (name == cx->runtime->atomState.byteLengthAtom) {
|
||||||
vp->setInt32(obj->asArrayBuffer().byteLength());
|
vp->setInt32(obj->asArrayBuffer().byteLength());
|
||||||
return true;
|
return true;
|
||||||
@ -787,12 +793,15 @@ ArrayBufferObject::obj_typeOf(JSContext *cx, JSObject *obj)
|
|||||||
* the subclasses.
|
* the subclasses.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
JSObject *
|
static JSObject *
|
||||||
TypedArray::getTypedArray(JSObject *obj)
|
getTypedArray(JSObject *obj)
|
||||||
{
|
{
|
||||||
while (!obj->isTypedArray())
|
MOZ_ASSERT(obj);
|
||||||
obj = obj->getProto();
|
do {
|
||||||
|
if (obj->isTypedArray())
|
||||||
return obj;
|
return obj;
|
||||||
|
} while ((obj = obj->getProto()));
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
@ -808,75 +817,60 @@ TypedArray::isArrayIndex(JSContext *cx, JSObject *obj, jsid id, uint32_t *ip)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef Value (* TypedArrayPropertyGetter)(JSObject *tarray);
|
|
||||||
|
|
||||||
template <TypedArrayPropertyGetter Get>
|
|
||||||
class TypedArrayGetter {
|
|
||||||
public:
|
|
||||||
static inline bool get(JSContext *cx, JSObject *obj, jsid id, Value *vp) {
|
|
||||||
do {
|
|
||||||
if (obj->isTypedArray()) {
|
|
||||||
JSObject *tarray = TypedArray::getTypedArray(obj);
|
|
||||||
if (tarray)
|
|
||||||
*vp = Get(tarray);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} while ((obj = obj->getProto()) != NULL);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For now (until slots directly hold data)
|
* For now (until slots directly hold data)
|
||||||
* slots data element points to the JSObject representing the ArrayBuffer.
|
* slots data element points to the JSObject representing the ArrayBuffer.
|
||||||
*/
|
*/
|
||||||
inline Value
|
|
||||||
getBufferValue(JSObject *tarray)
|
|
||||||
{
|
|
||||||
JSObject *buffer = TypedArray::getBuffer(tarray);
|
|
||||||
return ObjectValue(*buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
TypedArray::prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
TypedArray::prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||||
{
|
{
|
||||||
return TypedArrayGetter<getBufferValue>::get(cx, obj, id, vp);
|
if (!(obj = getTypedArray(obj))) {
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||||
|
JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "buffer", "object");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Value
|
JS_SET_RVAL(cx, vp, ObjectValue(*TypedArray::getBuffer(obj)));
|
||||||
getByteOffsetValue(JSObject *tarray)
|
return true;
|
||||||
{
|
|
||||||
return Int32Value(TypedArray::getByteOffset(tarray));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
TypedArray::prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
TypedArray::prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||||
{
|
{
|
||||||
return TypedArrayGetter<getByteOffsetValue>::get(cx, obj, id, vp);
|
if (!(obj = getTypedArray(obj))) {
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||||
|
JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "byteOffset", "object");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Value
|
JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getByteOffset(obj)));
|
||||||
getByteLengthValue(JSObject *tarray)
|
return true;
|
||||||
{
|
|
||||||
return Int32Value(TypedArray::getByteLength(tarray));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
TypedArray::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
TypedArray::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||||
{
|
{
|
||||||
return TypedArrayGetter<getByteLengthValue>::get(cx, obj, id, vp);
|
if (!(obj = getTypedArray(obj))) {
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||||
|
JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "byteLength", "object");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Value
|
JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getByteLength(obj)));
|
||||||
getLengthValue(JSObject *tarray)
|
return true;
|
||||||
{
|
|
||||||
return Int32Value(TypedArray::getLength(tarray));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
TypedArray::prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
TypedArray::prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||||
{
|
{
|
||||||
return TypedArrayGetter<getLengthValue>::get(cx, obj, id, vp);
|
if (!(obj = getTypedArray(obj))) {
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||||
|
JSMSG_INCOMPATIBLE_PROTO, "TypedArray", "length", "object");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_SET_RVAL(cx, vp, Int32Value(TypedArray::getLength(obj)));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSBool
|
JSBool
|
||||||
@ -1090,7 +1084,7 @@ class TypedArrayTemplate
|
|||||||
|
|
||||||
static inline Class *fastClass()
|
static inline Class *fastClass()
|
||||||
{
|
{
|
||||||
return &TypedArray::fastClasses[ArrayTypeID()];
|
return &TypedArray::classes[ArrayTypeID()];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1354,7 +1348,7 @@ class TypedArrayTemplate
|
|||||||
static JSBool
|
static JSBool
|
||||||
obj_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict)
|
obj_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict)
|
||||||
{
|
{
|
||||||
JSObject *tarray = TypedArray::getTypedArray(obj);
|
JSObject *tarray = getTypedArray(obj);
|
||||||
JS_ASSERT(tarray);
|
JS_ASSERT(tarray);
|
||||||
|
|
||||||
if (index < getLength(tarray)) {
|
if (index < getLength(tarray)) {
|
||||||
@ -1627,56 +1621,52 @@ class TypedArrayTemplate
|
|||||||
if (!tarray)
|
if (!tarray)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// these are the default values
|
|
||||||
int32_t off = 0;
|
|
||||||
|
|
||||||
if (args.length() > 1) {
|
|
||||||
if (!ToInt32(cx, args[1], &off))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (off < 0 || uint32_t(off) > getLength(tarray)) {
|
|
||||||
// the given offset is bogus
|
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
||||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t offset(off);
|
|
||||||
|
|
||||||
// first arg must be either a typed array or a JS array
|
// first arg must be either a typed array or a JS array
|
||||||
if (args.length() == 0 || !args[0].isObject()) {
|
if (args.length() == 0 || !args[0].isObject()) {
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t offset = 0;
|
||||||
|
if (args.length() > 1) {
|
||||||
|
if (!ToInt32(cx, args[1], &offset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (offset < 0 || uint32_t(offset) > getLength(tarray)) {
|
||||||
|
// the given offset is bogus
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_INDEX, "2");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!args[0].isObject()) {
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedVarObject arg0(cx, args[0].toObjectOrNull());
|
RootedVarObject arg0(cx, args[0].toObjectOrNull());
|
||||||
if (arg0->isTypedArray()) {
|
RootedVarObject src(getTypedArray(arg0));
|
||||||
JSObject *src = TypedArray::getTypedArray(arg0);
|
if (src) {
|
||||||
if (!src ||
|
if (getLength(src) > getLength(tarray) - offset) {
|
||||||
getLength(src) > getLength(tarray) - offset)
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
|
||||||
{
|
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
|
||||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!copyFromTypedArray(cx, obj, src, offset))
|
if (!copyFromTypedArray(cx, obj, src, offset))
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
src = arg0;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
if (!js_GetLengthProperty(cx, arg0, &len))
|
if (!js_GetLengthProperty(cx, src, &len))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// avoid overflow; we know that offset <= length
|
// avoid overflow; we know that offset <= length
|
||||||
if (len > getLength(tarray) - offset) {
|
if (len > getLength(tarray) - offset) {
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
|
||||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!copyFromArray(cx, obj, arg0, len, offset))
|
if (!copyFromArray(cx, obj, src, len, offset))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2145,10 +2135,7 @@ TypedArrayTemplate<float>::copyIndexToValue(JSContext *cx, JSObject *tarray, uin
|
|||||||
* This could be removed for platforms/compilers known to convert a 32-bit
|
* This could be removed for platforms/compilers known to convert a 32-bit
|
||||||
* non-canonical nan to a 64-bit canonical nan.
|
* non-canonical nan to a 64-bit canonical nan.
|
||||||
*/
|
*/
|
||||||
if (JS_UNLIKELY(MOZ_DOUBLE_IS_NaN(dval)))
|
vp->setDouble(JS_CANONICALIZE_NAN(dval));
|
||||||
dval = js_NaN;
|
|
||||||
|
|
||||||
vp->setDouble(dval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
@ -2335,7 +2322,7 @@ NewArrayWithBuffer(JSContext *cx, HandleObject arrayBuffer, int32_t byteoffset,
|
|||||||
{ \
|
{ \
|
||||||
obj = UnwrapObject(obj); \
|
obj = UnwrapObject(obj); \
|
||||||
Class *clasp = obj->getClass(); \
|
Class *clasp = obj->getClass(); \
|
||||||
return (clasp == &TypedArray::fastClasses[TypedArrayTemplate<NativeType>::ArrayTypeID()]); \
|
return (clasp == &TypedArray::classes[TypedArrayTemplate<NativeType>::ArrayTypeID()]); \
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int8, int8_t)
|
IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Int8, int8_t)
|
||||||
@ -2350,7 +2337,7 @@ IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float64, double)
|
|||||||
|
|
||||||
#define IMPL_TYPED_ARRAY_PROTO_CLASS(_typedArray) \
|
#define IMPL_TYPED_ARRAY_PROTO_CLASS(_typedArray) \
|
||||||
{ \
|
{ \
|
||||||
#_typedArray, \
|
#_typedArray "Prototype", \
|
||||||
JSCLASS_HAS_RESERVED_SLOTS(TypedArray::FIELD_MAX) | \
|
JSCLASS_HAS_RESERVED_SLOTS(TypedArray::FIELD_MAX) | \
|
||||||
JSCLASS_HAS_PRIVATE | \
|
JSCLASS_HAS_PRIVATE | \
|
||||||
JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray), \
|
JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray), \
|
||||||
@ -2475,7 +2462,7 @@ IMPL_TYPED_ARRAY_STATICS(Float32Array);
|
|||||||
IMPL_TYPED_ARRAY_STATICS(Float64Array);
|
IMPL_TYPED_ARRAY_STATICS(Float64Array);
|
||||||
IMPL_TYPED_ARRAY_STATICS(Uint8ClampedArray);
|
IMPL_TYPED_ARRAY_STATICS(Uint8ClampedArray);
|
||||||
|
|
||||||
Class TypedArray::fastClasses[TYPE_MAX] = {
|
Class TypedArray::classes[TYPE_MAX] = {
|
||||||
IMPL_TYPED_ARRAY_FAST_CLASS(Int8Array),
|
IMPL_TYPED_ARRAY_FAST_CLASS(Int8Array),
|
||||||
IMPL_TYPED_ARRAY_FAST_CLASS(Uint8Array),
|
IMPL_TYPED_ARRAY_FAST_CLASS(Uint8Array),
|
||||||
IMPL_TYPED_ARRAY_FAST_CLASS(Int16Array),
|
IMPL_TYPED_ARRAY_FAST_CLASS(Int16Array),
|
||||||
@ -2554,27 +2541,6 @@ js_InitTypedArrayClasses(JSContext *cx, JSObject *obj)
|
|||||||
return InitArrayBufferClass(cx, global);
|
return InitArrayBufferClass(cx, global);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
js::IsFastTypedArrayClass(const Class *clasp)
|
|
||||||
{
|
|
||||||
return &TypedArray::fastClasses[0] <= clasp &&
|
|
||||||
clasp < &TypedArray::fastClasses[TypedArray::TYPE_MAX];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool
|
|
||||||
IsSlowTypedArrayClass(const Class *clasp)
|
|
||||||
{
|
|
||||||
return &TypedArray::protoClasses[0] <= clasp &&
|
|
||||||
clasp < &TypedArray::protoClasses[TypedArray::TYPE_MAX];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
js::IsFastOrSlowTypedArray(JSObject *obj)
|
|
||||||
{
|
|
||||||
Class *clasp = obj->getClass();
|
|
||||||
return IsFastTypedArrayClass(clasp) || IsSlowTypedArrayClass(clasp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* JS Friend API */
|
/* JS Friend API */
|
||||||
|
|
||||||
JS_FRIEND_API(JSBool)
|
JS_FRIEND_API(JSBool)
|
||||||
|
@ -161,9 +161,6 @@ class ArrayBufferObject : public JSObject
|
|||||||
static JSType
|
static JSType
|
||||||
obj_typeOf(JSContext *cx, JSObject *obj);
|
obj_typeOf(JSContext *cx, JSObject *obj);
|
||||||
|
|
||||||
static JSObject *
|
|
||||||
getArrayBuffer(JSObject *obj);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
allocateSlots(JSContext *cx, uint32_t size, uint8_t *contents = NULL);
|
allocateSlots(JSContext *cx, uint32_t size, uint8_t *contents = NULL);
|
||||||
|
|
||||||
@ -218,7 +215,7 @@ struct TypedArray {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// and MUST NOT be used to construct new objects.
|
// and MUST NOT be used to construct new objects.
|
||||||
static Class fastClasses[TYPE_MAX];
|
static Class classes[TYPE_MAX];
|
||||||
|
|
||||||
// These are the proto/original classes, used
|
// These are the proto/original classes, used
|
||||||
// fo constructing new objects
|
// fo constructing new objects
|
||||||
@ -226,8 +223,6 @@ struct TypedArray {
|
|||||||
|
|
||||||
static JSPropertySpec jsprops[];
|
static JSPropertySpec jsprops[];
|
||||||
|
|
||||||
static JSObject *getTypedArray(JSObject *obj);
|
|
||||||
|
|
||||||
static JSBool prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
static JSBool prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
||||||
static JSBool prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
static JSBool prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
||||||
static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp);
|
||||||
@ -292,14 +287,31 @@ struct TypedArray {
|
|||||||
static int dataOffset();
|
static int dataOffset();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
inline bool
|
||||||
IsFastOrSlowTypedArray(JSObject *obj);
|
IsTypedArrayClass(const Class *clasp)
|
||||||
|
{
|
||||||
|
return &TypedArray::classes[0] <= clasp &&
|
||||||
|
clasp < &TypedArray::classes[TypedArray::TYPE_MAX];
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
inline bool
|
||||||
IsFastOrSlowTypedArrayClass(const Class *clasp);
|
IsTypedArrayProtoClass(const Class *clasp)
|
||||||
|
{
|
||||||
|
return &TypedArray::protoClasses[0] <= clasp &&
|
||||||
|
clasp < &TypedArray::protoClasses[TypedArray::TYPE_MAX];
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
inline bool
|
||||||
IsFastTypedArrayClass(const Class *clasp);
|
IsTypedArray(JSObject *obj)
|
||||||
|
{
|
||||||
|
return IsTypedArrayClass(obj->getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
IsTypedArrayProto(JSObject *obj)
|
||||||
|
{
|
||||||
|
return IsTypedArrayProtoClass(obj->getClass());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
@ -83,37 +83,37 @@ ClampIntForUint8Array(int32_t x)
|
|||||||
|
|
||||||
inline uint32_t
|
inline uint32_t
|
||||||
TypedArray::getLength(JSObject *obj) {
|
TypedArray::getLength(JSObject *obj) {
|
||||||
JS_ASSERT(IsFastOrSlowTypedArray(obj));
|
JS_ASSERT(obj->isTypedArray());
|
||||||
return obj->getFixedSlot(FIELD_LENGTH).toInt32();
|
return obj->getFixedSlot(FIELD_LENGTH).toInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t
|
inline uint32_t
|
||||||
TypedArray::getByteOffset(JSObject *obj) {
|
TypedArray::getByteOffset(JSObject *obj) {
|
||||||
JS_ASSERT(IsFastOrSlowTypedArray(obj));
|
JS_ASSERT(obj->isTypedArray());
|
||||||
return obj->getFixedSlot(FIELD_BYTEOFFSET).toInt32();
|
return obj->getFixedSlot(FIELD_BYTEOFFSET).toInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t
|
inline uint32_t
|
||||||
TypedArray::getByteLength(JSObject *obj) {
|
TypedArray::getByteLength(JSObject *obj) {
|
||||||
JS_ASSERT(IsFastOrSlowTypedArray(obj));
|
JS_ASSERT(obj->isTypedArray());
|
||||||
return obj->getFixedSlot(FIELD_BYTELENGTH).toInt32();
|
return obj->getFixedSlot(FIELD_BYTELENGTH).toInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t
|
inline uint32_t
|
||||||
TypedArray::getType(JSObject *obj) {
|
TypedArray::getType(JSObject *obj) {
|
||||||
JS_ASSERT(IsFastOrSlowTypedArray(obj));
|
JS_ASSERT(obj->isTypedArray());
|
||||||
return obj->getFixedSlot(FIELD_TYPE).toInt32();
|
return obj->getFixedSlot(FIELD_TYPE).toInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ArrayBufferObject *
|
inline ArrayBufferObject *
|
||||||
TypedArray::getBuffer(JSObject *obj) {
|
TypedArray::getBuffer(JSObject *obj) {
|
||||||
JS_ASSERT(IsFastOrSlowTypedArray(obj));
|
JS_ASSERT(obj->isTypedArray());
|
||||||
return &obj->getFixedSlot(FIELD_BUFFER).toObject().asArrayBuffer();
|
return &obj->getFixedSlot(FIELD_BUFFER).toObject().asArrayBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void *
|
inline void *
|
||||||
TypedArray::getDataOffset(JSObject *obj) {
|
TypedArray::getDataOffset(JSObject *obj) {
|
||||||
JS_ASSERT(IsFastOrSlowTypedArray(obj));
|
JS_ASSERT(obj->isTypedArray());
|
||||||
return (void *)obj->getPrivate(NUM_FIXED_SLOTS);
|
return (void *)obj->getPrivate(NUM_FIXED_SLOTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2319,17 +2319,16 @@ GetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, const Value &v, jsid i
|
|||||||
? Int32Key::FromConstant(v.toInt32())
|
? Int32Key::FromConstant(v.toInt32())
|
||||||
: Int32Key::FromRegister(idRemat.dataReg());
|
: Int32Key::FromRegister(idRemat.dataReg());
|
||||||
|
|
||||||
JSObject *tarray = js::TypedArray::getTypedArray(obj);
|
|
||||||
if (!masm.supportsFloatingPoint() &&
|
if (!masm.supportsFloatingPoint() &&
|
||||||
(TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32 ||
|
(TypedArray::getType(obj) == TypedArray::TYPE_FLOAT32 ||
|
||||||
TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT64 ||
|
TypedArray::getType(obj) == TypedArray::TYPE_FLOAT64 ||
|
||||||
TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT32))
|
TypedArray::getType(obj) == TypedArray::TYPE_UINT32))
|
||||||
{
|
{
|
||||||
return disable(f, "fpu not supported");
|
return disable(f, "fpu not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeRegisterID tempReg;
|
MaybeRegisterID tempReg;
|
||||||
masm.loadFromTypedArray(TypedArray::getType(tarray), objReg, key, typeReg, objReg, tempReg);
|
masm.loadFromTypedArray(TypedArray::getType(obj), objReg, key, typeReg, objReg, tempReg);
|
||||||
|
|
||||||
Jump done = masm.jump();
|
Jump done = masm.jump();
|
||||||
|
|
||||||
@ -2633,18 +2632,17 @@ SetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, int32_t key)
|
|||||||
// Load the array's packed data vector.
|
// Load the array's packed data vector.
|
||||||
masm.loadPtr(Address(objReg, TypedArray::dataOffset()), objReg);
|
masm.loadPtr(Address(objReg, TypedArray::dataOffset()), objReg);
|
||||||
|
|
||||||
JSObject *tarray = js::TypedArray::getTypedArray(obj);
|
|
||||||
if (!masm.supportsFloatingPoint() &&
|
if (!masm.supportsFloatingPoint() &&
|
||||||
(TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32 ||
|
(TypedArray::getType(obj) == TypedArray::TYPE_FLOAT32 ||
|
||||||
TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT64))
|
TypedArray::getType(obj) == TypedArray::TYPE_FLOAT64))
|
||||||
{
|
{
|
||||||
return disable(f, "fpu not supported");
|
return disable(f, "fpu not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
int shift = js::TypedArray::slotWidth(obj);
|
int shift = TypedArray::slotWidth(obj);
|
||||||
if (hasConstantKey) {
|
if (hasConstantKey) {
|
||||||
Address addr(objReg, keyValue * shift);
|
Address addr(objReg, keyValue * shift);
|
||||||
if (!StoreToTypedArray(cx, masm, tarray, addr, vr, volatileMask))
|
if (!StoreToTypedArray(cx, masm, obj, addr, vr, volatileMask))
|
||||||
return error(cx);
|
return error(cx);
|
||||||
} else {
|
} else {
|
||||||
Assembler::Scale scale = Assembler::TimesOne;
|
Assembler::Scale scale = Assembler::TimesOne;
|
||||||
@ -2660,7 +2658,7 @@ SetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, int32_t key)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BaseIndex addr(objReg, keyReg, scale);
|
BaseIndex addr(objReg, keyReg, scale);
|
||||||
if (!StoreToTypedArray(cx, masm, tarray, addr, vr, volatileMask))
|
if (!StoreToTypedArray(cx, masm, obj, addr, vr, volatileMask))
|
||||||
return error(cx);
|
return error(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3409,17 +3409,16 @@ Deserialize(JSContext *cx, unsigned argc, jsval *vp)
|
|||||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize");
|
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
JSObject *array = TypedArray::getTypedArray(obj);
|
if ((TypedArray::getByteLength(obj) & 7) != 0) {
|
||||||
if ((TypedArray::getByteLength(array) & 7) != 0) {
|
|
||||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize");
|
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((uintptr_t(TypedArray::getDataOffset(array)) & 7) != 0) {
|
if ((uintptr_t(TypedArray::getDataOffset(obj)) & 7) != 0) {
|
||||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_BAD_ALIGNMENT);
|
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_BAD_ALIGNMENT);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!JS_ReadStructuredClone(cx, (uint64_t *) TypedArray::getDataOffset(array), TypedArray::getByteLength(array),
|
if (!JS_ReadStructuredClone(cx, (uint64_t *) TypedArray::getDataOffset(obj), TypedArray::getByteLength(obj),
|
||||||
JS_STRUCTURED_CLONE_VERSION, v.address(), NULL, NULL)) {
|
JS_STRUCTURED_CLONE_VERSION, v.address(), NULL, NULL)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ function test()
|
|||||||
|
|
||||||
var TODO = 1;
|
var TODO = 1;
|
||||||
|
|
||||||
function check(fun, todo) {
|
function check(fun, msg, todo) {
|
||||||
var thrown = null;
|
var thrown = null;
|
||||||
var success = false;
|
var success = false;
|
||||||
try {
|
try {
|
||||||
@ -60,6 +60,8 @@ function test()
|
|||||||
|
|
||||||
var ex = new Error;
|
var ex = new Error;
|
||||||
print ("=== FAILED ===");
|
print ("=== FAILED ===");
|
||||||
|
if (msg)
|
||||||
|
print (msg);
|
||||||
print (ex.stack);
|
print (ex.stack);
|
||||||
if (thrown) {
|
if (thrown) {
|
||||||
print (" threw exception:");
|
print (" threw exception:");
|
||||||
@ -69,18 +71,29 @@ function test()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkThrows(fun, todo) {
|
function checkThrows(fun, type, todo) {
|
||||||
let thrown = false;
|
var thrown = false;
|
||||||
try {
|
try {
|
||||||
fun();
|
fun();
|
||||||
} catch (x) {
|
} catch (x) {
|
||||||
thrown = true;
|
thrown = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
check(function() thrown, todo);
|
if (typeof(type) !== 'undefined')
|
||||||
|
if (thrown) {
|
||||||
|
check(function () thrown instanceof type,
|
||||||
|
"expected " + type.name + " but saw " + thrown,
|
||||||
|
todo);
|
||||||
|
} else {
|
||||||
|
check(function () thrown, "expected " + type.name + " but no exception thrown", todo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
check(function () thrown, undefined, todo);
|
||||||
}
|
}
|
||||||
|
|
||||||
check(function() ArrayBuffer.prototype.byteLength == 0);
|
function checkThrowsTODO(fun, type) {
|
||||||
|
checkThrows(fun, type, true);
|
||||||
|
}
|
||||||
|
|
||||||
var buf, buf2;
|
var buf, buf2;
|
||||||
|
|
||||||
@ -101,9 +114,9 @@ function test()
|
|||||||
var zerobuf2 = new ArrayBuffer();
|
var zerobuf2 = new ArrayBuffer();
|
||||||
check(function() zerobuf2.byteLength == 0);
|
check(function() zerobuf2.byteLength == 0);
|
||||||
|
|
||||||
checkThrows(function() new ArrayBuffer(-100));
|
checkThrows(function() new ArrayBuffer(-100), RangeError);
|
||||||
// this is using js_ValueToECMAUInt32, which is giving 0 for "abc"
|
// this is using js_ValueToECMAUInt32, which is giving 0 for "abc"
|
||||||
checkThrows(function() new ArrayBuffer("abc"), TODO);
|
checkThrowsTODO(function() new ArrayBuffer("abc"), TypeError);
|
||||||
|
|
||||||
var zeroarray = new Int32Array(0);
|
var zeroarray = new Int32Array(0);
|
||||||
check(function() zeroarray.length == 0);
|
check(function() zeroarray.length == 0);
|
||||||
@ -187,15 +200,15 @@ function test()
|
|||||||
check(function() a[1] == 0xbb);
|
check(function() a[1] == 0xbb);
|
||||||
|
|
||||||
// not sure if this is supposed to throw or to treat "foo"" as 0.
|
// not sure if this is supposed to throw or to treat "foo"" as 0.
|
||||||
checkThrows(function() new Int32Array([0xaa, "foo", 0xbb]), TODO);
|
checkThrowsTODO(function() new Int32Array([0xaa, "foo", 0xbb]), Error);
|
||||||
|
|
||||||
checkThrows(function() new Int32Array(-100));
|
checkThrows(function() new Int32Array(-100));
|
||||||
|
|
||||||
a = new Uint8Array(3);
|
a = new Uint8Array(3);
|
||||||
// XXX these are ignored now and return undefined
|
// XXX these are ignored now and return undefined
|
||||||
//checkThrows(function() a[5000] = 0);
|
//checkThrows(function() a[5000] = 0, RangeError);
|
||||||
//checkThrows(function() a["hello"] = 0);
|
//checkThrows(function() a["hello"] = 0, TypeError);
|
||||||
//checkThrows(function() a[-10] = 0);
|
//checkThrows(function() a[-10] = 0, RangeError);
|
||||||
check(function() (a[0] = "10") && (a[0] == 10));
|
check(function() (a[0] = "10") && (a[0] == 10));
|
||||||
|
|
||||||
// check Uint8ClampedArray, which is an extension to this extension
|
// check Uint8ClampedArray, which is an extension to this extension
|
||||||
@ -265,8 +278,8 @@ function test()
|
|||||||
checkThrows(function() a.set([1,2,3], 2147483647));
|
checkThrows(function() a.set([1,2,3], 2147483647));
|
||||||
|
|
||||||
a.set(ArrayBuffer.prototype);
|
a.set(ArrayBuffer.prototype);
|
||||||
a.set(Int16Array.prototype);
|
checkThrows(function () a.set(Int16Array.prototype), TypeError);
|
||||||
a.set(Int32Array.prototype);
|
checkThrows(function () a.set(Int32Array.prototype), TypeError);
|
||||||
|
|
||||||
a.set([1,2,3]);
|
a.set([1,2,3]);
|
||||||
a.set([4,5,6], 3);
|
a.set([4,5,6], 3);
|
||||||
@ -317,16 +330,43 @@ function test()
|
|||||||
a = new Uint8Array(0x100);
|
a = new Uint8Array(0x100);
|
||||||
checkThrows(function() Uint32Array.prototype.subarray.apply(a, [0, 0x100]));
|
checkThrows(function() Uint32Array.prototype.subarray.apply(a, [0, 0x100]));
|
||||||
|
|
||||||
// The prototypes are objects that don't have a length property, so they act
|
// webidl section 4.4.6, getter bullet point 2.2: prototypes are not
|
||||||
// like empty arrays.
|
// platform objects, and calling the getter of any attribute defined on the
|
||||||
check(function() new Int32Array(ArrayBuffer.prototype).length == 0);
|
// interface should throw a TypeError according to
|
||||||
check(function() new Int32Array(Int32Array.prototype).length == 0);
|
checkThrows(function() ArrayBuffer.prototype.byteLength, TypeError);
|
||||||
check(function() new Int32Array(Float64Array.prototype).length == 0);
|
checkThrows(function() Int32Array.prototype.length, TypeError);
|
||||||
|
checkThrows(function() Int32Array.prototype.byteLength, TypeError);
|
||||||
|
checkThrows(function() Int32Array.prototype.byteOffset, TypeError);
|
||||||
|
checkThrows(function() Float64Array.prototype.length, TypeError);
|
||||||
|
checkThrows(function() Float64Array.prototype.byteLength, TypeError);
|
||||||
|
checkThrows(function() Float64Array.prototype.byteOffset, TypeError);
|
||||||
|
|
||||||
// ArrayBuffer, Int32Array and Float64Array are native functions and have a .length
|
// webidl 4.4.6: a readonly attribute's setter is undefined. From
|
||||||
// checkThrows(function() new Int32Array(ArrayBuffer));
|
// observation, that seems to mean it silently does nothing, and returns
|
||||||
// checkThrows(function() new Int32Array(Int32Array));
|
// the value that you tried to set it to.
|
||||||
// checkThrows(function() new Int32Array(Float64Array));
|
check(function() Int32Array.prototype.length = true);
|
||||||
|
check(function() Float64Array.prototype.length = true);
|
||||||
|
check(function() Int32Array.prototype.byteLength = true);
|
||||||
|
check(function() Float64Array.prototype.byteLength = true);
|
||||||
|
check(function() Int32Array.prototype.byteOffset = true);
|
||||||
|
check(function() Float64Array.prototype.byteOffset = true);
|
||||||
|
|
||||||
|
// ArrayBuffer, Int32Array and Float64Array are native functions and have a
|
||||||
|
// .length, so none of these should throw:
|
||||||
|
check(function() (new Int32Array(ArrayBuffer)).length >= 0);
|
||||||
|
check(function() (new Int32Array(Int32Array)).length >= 0);
|
||||||
|
check(function() (new Int32Array(Float64Array)).length >= 0);
|
||||||
|
|
||||||
|
// webidl 4.4.6, under getters: "The value of the Function object’s
|
||||||
|
// 'length' property is the Number value 0"
|
||||||
|
//
|
||||||
|
// Except this fails in getOwnPropertyDescriptor, I think because
|
||||||
|
// Int32Array.prototype does not provide a lookup hook, and the fallback
|
||||||
|
// case ends up calling the getter. Which seems odd to me, but much of this
|
||||||
|
// stuff baffles me. It does seem strange that there's no way to do
|
||||||
|
// getOwnPropertyDescriptor on any of these attributes.
|
||||||
|
//
|
||||||
|
//check(Object.getOwnPropertyDescriptor(Int32Array.prototype, 'byteOffset')['get'].length == 0);
|
||||||
|
|
||||||
check(function() Int32Array.BYTES_PER_ELEMENT == 4);
|
check(function() Int32Array.BYTES_PER_ELEMENT == 4);
|
||||||
check(function() (new Int32Array(4)).BYTES_PER_ELEMENT == 4);
|
check(function() (new Int32Array(4)).BYTES_PER_ELEMENT == 4);
|
||||||
|
Loading…
Reference in New Issue
Block a user