Bug 636078 - Fix some typed array bugs. r=vlad, r=jorendorff

This commit is contained in:
Jeff Walden 2011-02-24 01:23:57 -08:00
Родитель ab404c48d1
Коммит eb38099001
2 изменённых файлов: 213 добавлений и 256 удалений

Просмотреть файл

@ -133,23 +133,23 @@ ArrayBuffer::class_finalize(JSContext *cx, JSObject *obj)
JSBool JSBool
ArrayBuffer::class_constructor(JSContext *cx, uintN argc, Value *vp) ArrayBuffer::class_constructor(JSContext *cx, uintN argc, Value *vp)
{ {
return create(cx, argc, JS_ARGV(cx, vp), vp); int32 nbytes = 0;
} if (argc > 0 && !ValueToECMAInt32(cx, vp[2], &nbytes))
bool
ArrayBuffer::create(JSContext *cx, uintN argc, Value *argv, Value *rval)
{
/* N.B. there may not be an argv[-2]/argv[-1]. */
JSObject *obj = NewBuiltinClassInstance(cx, &ArrayBuffer::jsclass);
if (!obj)
return false; return false;
int32_t nbytes = 0; JSObject *bufobj = create(cx, nbytes);
if (argc > 0) { if (!bufobj)
if (!ValueToECMAInt32(cx, argv[0], &nbytes)) return false;
return false; vp->setObject(*bufobj);
} return true;
}
JSObject *
ArrayBuffer::create(JSContext *cx, int32 nbytes)
{
JSObject *obj = NewBuiltinClassInstance(cx, &ArrayBuffer::jsclass);
if (!obj)
return NULL;
if (nbytes < 0) { if (nbytes < 0) {
/* /*
@ -157,25 +157,21 @@ ArrayBuffer::create(JSContext *cx, uintN argc, Value *argv, Value *rval)
* as an integer value; if someone actually ever complains (validly), then we * as an integer value; if someone actually ever complains (validly), then we
* can fix. * can fix.
*/ */
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
JSMSG_BAD_ARRAY_LENGTH); return NULL;
return false;
} }
ArrayBuffer *abuf = cx->create<ArrayBuffer>(); ArrayBuffer *abuf = cx->create<ArrayBuffer>();
if (!abuf) { if (!abuf)
JS_ReportOutOfMemory(cx); return NULL;
return false;
}
if (!abuf->allocateStorage(cx, nbytes)) { if (!abuf->allocateStorage(cx, nbytes)) {
cx->destroy<ArrayBuffer>(abuf); cx->destroy<ArrayBuffer>(abuf);
return false; return NULL;
} }
obj->setPrivate(abuf); obj->setPrivate(abuf);
rval->setObject(*obj); return obj;
return true;
} }
bool bool
@ -185,10 +181,8 @@ ArrayBuffer::allocateStorage(JSContext *cx, uint32 nbytes)
if (nbytes) { if (nbytes) {
data = cx->calloc(nbytes); data = cx->calloc(nbytes);
if (!data) { if (!data)
JS_ReportOutOfMemory(cx);
return false; return false;
}
} }
byteLength = nbytes; byteLength = nbytes;
@ -726,6 +720,28 @@ class TypedArrayTemplate
return JSTYPE_OBJECT; return JSTYPE_OBJECT;
} }
static JSObject *
createTypedArray(JSContext *cx, JSObject *bufobj, uint32 byteOffset, uint32 len)
{
JSObject *obj = NewBuiltinClassInstance(cx, slowClass());
if (!obj)
return NULL;
ThisTypeArray *tarray = cx->create<ThisTypeArray>(bufobj, byteOffset, len);
if (!tarray)
return NULL;
JS_ASSERT(obj->getClass() == slowClass());
obj->setSharedNonNativeMap();
obj->clasp = fastClass();
obj->setPrivate(tarray);
// FIXME Bug 599008: make it ok to call preventExtensions here.
obj->flags |= JSObject::NOT_EXTENSIBLE;
return obj;
}
/* /*
* new [Type]Array(length) * new [Type]Array(length)
* new [Type]Array(otherTypedArray) * new [Type]Array(otherTypedArray)
@ -736,80 +752,79 @@ class TypedArrayTemplate
class_constructor(JSContext *cx, uintN argc, Value *vp) class_constructor(JSContext *cx, uintN argc, Value *vp)
{ {
/* N.B. this is a constructor for slowClass, not fastClass! */ /* N.B. this is a constructor for slowClass, not fastClass! */
return create(cx, argc, JS_ARGV(cx, vp), vp); JSObject *obj = create(cx, argc, JS_ARGV(cx, vp));
if (!obj)
return false;
vp->setObject(*obj);
return true;
} }
static JSBool static JSObject *
create(JSContext *cx, uintN argc, Value *argv, Value *rval) create(JSContext *cx, uintN argc, Value *argv)
{ {
/* N.B. there may not be an argv[-2]/argv[-1]. */ /* N.B. there may not be an argv[-2]/argv[-1]. */
JSObject *obj = NewBuiltinClassInstance(cx, slowClass()); /* () or (number) */
if (!obj)
return false;
ThisTypeArray *tarray = 0;
// figure out the type of the first argument;
// no args is treated like an int arg of 0.
jsuint len = 0; jsuint len = 0;
bool hasLen = true; if (argc == 0 || ValueIsLength(cx, argv[0], &len)) {
if (argc > 0) JSObject *bufobj = createBufferWithSizeAndCount(cx, len);
hasLen = ValueIsLength(cx, argv[0], &len); if (!bufobj)
return NULL;
if (hasLen) { return createTypedArray(cx, bufobj, 0, len);
tarray = cx->create<ThisTypeArray>(); }
if (!tarray) {
JS_ReportOutOfMemory(cx);
return false;
}
if (!tarray->init(cx, len)) { /* (not an object) */
cx->destroy<ThisTypeArray>(tarray); if (!argv[0].isObject()) {
return false; JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
} JSMSG_TYPED_ARRAY_BAD_ARGS);
} else if (argc > 0 && argv[0].isObject()) { return NULL;
int32_t byteOffset = -1; }
int32_t length = -1;
if (argc > 1) { JSObject *dataObj = &argv[0].toObject();
if (!ValueToInt32(cx, argv[1], &byteOffset))
return false; /* (typedArray) */
if (byteOffset < 0) { if (js_IsTypedArray(dataObj)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, TypedArray *otherTypedArray = TypedArray::fromJSObject(dataObj);
JSMSG_TYPED_ARRAY_NEGATIVE_ARG, "1"); JS_ASSERT(otherTypedArray);
return false;
} uint32 len = otherTypedArray->length;
JSObject *bufobj = createBufferWithSizeAndCount(cx, len);
if (!bufobj)
return NULL;
JSObject *obj = createTypedArray(cx, bufobj, 0, len);
if (!obj || !copyFrom(cx, obj, otherTypedArray, 0))
return NULL;
return obj;
}
/* (obj, byteOffset, length). */
int32_t byteOffset = -1;
int32_t length = -1;
if (argc > 1) {
if (!ValueToInt32(cx, argv[1], &byteOffset))
return NULL;
if (byteOffset < 0) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_NEGATIVE_ARG, "1");
return NULL;
} }
if (argc > 2) { if (argc > 2) {
if (!ValueToInt32(cx, argv[2], &length)) if (!ValueToInt32(cx, argv[2], &length))
return false; return NULL;
if (length < 0) { if (length < 0) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_NEGATIVE_ARG, "2"); JSMSG_TYPED_ARRAY_NEGATIVE_ARG, "2");
return false; return NULL;
} }
} }
tarray = cx->create<ThisTypeArray>();
if (!tarray) {
JS_ReportOutOfMemory(cx);
return false;
}
if (!tarray->init(cx, &argv[0].toObject(), byteOffset, length)) {
cx->destroy<ThisTypeArray>(tarray);
return false;
}
} else {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
} }
rval->setObject(*obj); /* (obj, byteOffset, length) */
return makeFastWithPrivate(cx, obj, tarray); return createTypedArrayWithOffsetLength(cx, dataObj, byteOffset, length);
} }
static void static void
@ -875,25 +890,11 @@ class TypedArrayTemplate
if (begin > end) if (begin > end)
begin = end; begin = end;
ThisTypeArray *ntarray = tarray->subarray(cx, begin, end); JSObject *nobj = createSubarray(cx, tarray, begin, end);
if (!ntarray) { if (!nobj)
// this should rarely ever happen
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return false; return false;
}
// note the usage of NewObject here -- we don't want the
// constructor to be called!
JS_ASSERT(slowClass() != &js_FunctionClass);
JSObject *nobj = NewNonFunction<WithProto::Class>(cx, slowClass(), NULL, NULL);
if (!nobj) {
cx->destroy<ThisTypeArray>(ntarray);
return false;
}
vp->setObject(*nobj); vp->setObject(*nobj);
return makeFastWithPrivate(cx, nobj, ntarray); return true;
} }
/* set(array[, offset]) */ /* set(array[, offset]) */
@ -920,14 +921,14 @@ class TypedArrayTemplate
return true; return true;
// these are the default values // these are the default values
int32_t offset = 0; int32_t off = 0;
Value *argv = JS_ARGV(cx, vp); Value *argv = JS_ARGV(cx, vp);
if (argc > 1) { if (argc > 1) {
if (!ValueToInt32(cx, argv[1], &offset)) if (!ValueToInt32(cx, argv[1], &off))
return false; return false;
if (offset < 0 || uint32_t(offset) > tarray->length) { if (off < 0 || uint32_t(off) > tarray->length) {
// the given offset is bogus // the given offset is bogus
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS); JSMSG_TYPED_ARRAY_BAD_ARGS);
@ -935,6 +936,8 @@ class TypedArrayTemplate
} }
} }
uint32 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 (argc == 0 || !argv[0].isObject()) { if (argc == 0 || !argv[0].isObject()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
@ -953,7 +956,7 @@ class TypedArrayTemplate
return false; return false;
} }
if (!tarray->copyFrom(cx, src, offset)) if (!copyFrom(cx, obj, src, offset))
return false; return false;
} else { } else {
jsuint len; jsuint len;
@ -967,7 +970,7 @@ class TypedArrayTemplate
return false; return false;
} }
if (!tarray->copyFrom(cx, arg0, len, offset)) if (!copyFrom(cx, obj, arg0, len, offset))
return false; return false;
} }
@ -982,53 +985,44 @@ class TypedArrayTemplate
return reinterpret_cast<ThisTypeArray*>(obj->getPrivate()); return reinterpret_cast<ThisTypeArray*>(obj->getPrivate());
} }
// helper used by both the constructor and Subarray()
static bool
makeFastWithPrivate(JSContext *cx, JSObject *obj, ThisTypeArray *tarray)
{
JS_ASSERT(obj->getClass() == slowClass());
obj->setSharedNonNativeMap();
obj->clasp = fastClass();
obj->setPrivate(tarray);
// FIXME bug 599008. make it ok to call preventExtensions here.
// Keeping the boolean signature of this method for now.
obj->flags |= JSObject::NOT_EXTENSIBLE;
return true;
}
public: public:
TypedArrayTemplate() { } TypedArrayTemplate(JSObject *bufobj, uint32 byteOffset, uint32 len)
bool
init(JSContext *cx, uint32 len)
{ {
JS_ASSERT(bufobj->getClass() == &ArrayBuffer::jsclass);
type = ArrayTypeID(); type = ArrayTypeID();
return createBufferWithSizeAndCount(cx, sizeof(NativeType), len); bufferJS = bufobj;
buffer = ArrayBuffer::fromJSObject(bufobj);
this->byteOffset = byteOffset;
JS_ASSERT(byteOffset <= buffer->byteLength);
this->data = buffer->offsetData(byteOffset);
JS_ASSERT(buffer->data <= this->data);
JS_ASSERT(this->data <= buffer->offsetData(buffer->byteLength));
this->byteLength = len * sizeof(NativeType);
JS_ASSERT(buffer->byteLength - byteOffset >= this->byteLength);
this->length = len;
} }
bool static JSObject *
init(JSContext *cx, JSObject *other, int32 byteOffsetInt = -1, int32 lengthInt = -1) createTypedArrayWithOffsetLength(JSContext *cx, JSObject *other,
int32 byteOffsetInt, int32 lengthInt)
{ {
type = ArrayTypeID(); JS_ASSERT(!js_IsTypedArray(other));
/* Handle creation from an ArrayBuffer not ArrayBuffer.prototype. */
ArrayBuffer *abuf; ArrayBuffer *abuf;
if (other->getClass() == &ArrayBuffer::jsclass &&
if (js_IsTypedArray(other)) {
TypedArray *tarray = TypedArray::fromJSObject(other);
JS_ASSERT(tarray);
if (!createBufferWithSizeAndCount(cx, sizeof(NativeType), tarray->length))
return false;
if (!copyFrom(cx, tarray))
return false;
} else if (other->getClass() == &ArrayBuffer::jsclass &&
((abuf = ArrayBuffer::fromJSObject(other)) != NULL)) { ((abuf = ArrayBuffer::fromJSObject(other)) != NULL)) {
uint32 boffset = (byteOffsetInt < 0) ? 0 : uint32(byteOffsetInt); uint32 boffset = (byteOffsetInt < 0) ? 0 : uint32(byteOffsetInt);
if (boffset > abuf->byteLength || boffset % sizeof(NativeType) != 0) { if (boffset > abuf->byteLength || boffset % sizeof(NativeType) != 0) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS); JSMSG_TYPED_ARRAY_BAD_ARGS);
return false; // invalid byteOffset return NULL; // invalid byteOffset
} }
uint32 len; uint32 len;
@ -1037,7 +1031,7 @@ class TypedArrayTemplate
if (len * sizeof(NativeType) != (abuf->byteLength - boffset)) { if (len * sizeof(NativeType) != (abuf->byteLength - boffset)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS); JSMSG_TYPED_ARRAY_BAD_ARGS);
return false; // given byte array doesn't map exactly to sizeof(NativeType)*N return NULL; // given byte array doesn't map exactly to sizeof(NativeType)*N
} }
} else { } else {
len = (uint32) lengthInt; len = (uint32) lengthInt;
@ -1050,32 +1044,34 @@ class TypedArrayTemplate
{ {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS); JSMSG_TYPED_ARRAY_BAD_ARGS);
return false; // overflow occurred along the way when calculating boffset+len*sizeof(NativeType) return NULL; // overflow occurred along the way when calculating boffset+len*sizeof(NativeType)
} }
if (arrayByteLength + boffset > abuf->byteLength) { if (arrayByteLength + boffset > abuf->byteLength) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS); JSMSG_TYPED_ARRAY_BAD_ARGS);
return false; // boffset+len is too big for the arraybuffer return NULL; // boffset+len is too big for the arraybuffer
} }
buffer = abuf; return createTypedArray(cx, other, boffset, len);
bufferJS = other;
byteOffset = boffset;
byteLength = arrayByteLength;
length = len;
data = abuf->offsetData(boffset);
} else {
jsuint len;
if (!js_GetLengthProperty(cx, other, &len))
return false;
if (!createBufferWithSizeAndCount(cx, sizeof(NativeType), len))
return false;
if (!copyFrom(cx, other, len))
return false;
} }
return true; /*
* Otherwise create a new typed array and copy len properties from the
* object.
*/
jsuint len;
if (!js_GetLengthProperty(cx, other, &len))
return NULL;
JSObject *bufobj = createBufferWithSizeAndCount(cx, len);
if (!bufobj)
return NULL;
JSObject *obj = createTypedArray(cx, bufobj, 0, len);
if (!obj || !copyFrom(cx, obj, other, len))
return NULL;
return obj;
} }
const NativeType const NativeType
@ -1092,25 +1088,26 @@ class TypedArrayTemplate
inline void copyIndexToValue(JSContext *cx, uint32 index, Value *vp); inline void copyIndexToValue(JSContext *cx, uint32 index, Value *vp);
ThisTypeArray * static JSObject *
subarray(JSContext *cx, uint32 begin, uint32 end) createSubarray(JSContext *cx, ThisTypeArray *tarray, uint32 begin, uint32 end)
{ {
if (begin > length || end > length) JS_ASSERT(tarray);
return NULL;
ThisTypeArray *tarray = cx->create<ThisTypeArray>(); JS_ASSERT(0 <= begin);
if (!tarray) JS_ASSERT(begin <= tarray->length);
return NULL; JS_ASSERT(0 <= end);
JS_ASSERT(end <= tarray->length);
tarray->buffer = buffer; JSObject *bufobj = tarray->bufferJS;
tarray->bufferJS = bufferJS; JS_ASSERT(bufobj);
tarray->byteOffset = byteOffset + begin * sizeof(NativeType);
tarray->byteLength = (end - begin) * sizeof(NativeType);
tarray->length = end - begin;
tarray->type = type;
tarray->data = buffer->offsetData(tarray->byteOffset);
return tarray; JS_ASSERT(begin <= end);
uint32 length = end - begin;
JS_ASSERT(begin < UINT32_MAX / sizeof(NativeType));
uint32 byteOffset = begin * sizeof(NativeType);
return createTypedArray(cx, bufobj, byteOffset, length);
} }
protected: protected:
@ -1139,12 +1136,16 @@ class TypedArrayTemplate
return NativeType(int32(0)); return NativeType(int32(0));
} }
bool static bool
copyFrom(JSContext *cx, JSObject *ar, jsuint len, jsuint offset = 0) copyFrom(JSContext *cx, JSObject *thisTypedArrayObj,
JSObject *ar, jsuint len, jsuint offset = 0)
{ {
JS_ASSERT(offset <= length); ThisTypeArray *thisTypedArray = fromJSObject(thisTypedArrayObj);
JS_ASSERT(len <= length - offset); JS_ASSERT(thisTypedArray);
NativeType *dest = static_cast<NativeType*>(data) + offset;
JS_ASSERT(offset <= thisTypedArray->length);
JS_ASSERT(len <= thisTypedArray->length - offset);
NativeType *dest = static_cast<NativeType*>(thisTypedArray->data) + offset;
if (ar->isDenseArray() && ar->getDenseArrayCapacity() >= len) { if (ar->isDenseArray() && ar->getDenseArrayCapacity() >= len) {
JS_ASSERT(ar->getArrayLength() == len); JS_ASSERT(ar->getArrayLength() == len);
@ -1167,17 +1168,20 @@ class TypedArrayTemplate
return true; return true;
} }
bool static bool
copyFrom(JSContext *cx, TypedArray *tarray, jsuint offset = 0) copyFrom(JSContext *cx, JSObject *thisTypedArrayObj, TypedArray *tarray, jsuint offset)
{ {
JS_ASSERT(offset <= length); ThisTypeArray *thisTypedArray = fromJSObject(thisTypedArrayObj);
JS_ASSERT(tarray->length <= length - offset); JS_ASSERT(thisTypedArray);
if (tarray->buffer == buffer)
return copyFromWithOverlap(cx, tarray, offset);
NativeType *dest = static_cast<NativeType*>(data) + offset; JS_ASSERT(offset <= thisTypedArray->length);
JS_ASSERT(tarray->length <= thisTypedArray->length - offset);
if (tarray->buffer == thisTypedArray->buffer)
return thisTypedArray->copyFromWithOverlap(cx, tarray, offset);
if (tarray->type == type) { NativeType *dest = static_cast<NativeType*>(thisTypedArray->data) + offset;
if (tarray->type == thisTypedArray->type) {
memcpy(dest, tarray->data, tarray->byteLength); memcpy(dest, tarray->data, tarray->byteLength);
return true; return true;
} }
@ -1242,7 +1246,7 @@ class TypedArrayTemplate
} }
bool bool
copyFromWithOverlap(JSContext *cx, TypedArray *tarray, jsuint offset = 0) copyFromWithOverlap(JSContext *cx, TypedArray *tarray, jsuint offset)
{ {
JS_ASSERT(offset <= length); JS_ASSERT(offset <= length);
@ -1255,11 +1259,9 @@ class TypedArrayTemplate
// We have to make a copy of the source array here, since // We have to make a copy of the source array here, since
// there's overlap, and we have to convert types. // there's overlap, and we have to convert types.
void *srcbuf = js_malloc(tarray->byteLength); void *srcbuf = cx->malloc(tarray->byteLength);
if (!srcbuf) { if (!srcbuf)
js_ReportOutOfMemory(cx);
return false; return false;
}
memcpy(srcbuf, tarray->data, tarray->byteLength); memcpy(srcbuf, tarray->data, tarray->byteLength);
switch (tarray->type) { switch (tarray->type) {
@ -1321,11 +1323,10 @@ class TypedArrayTemplate
return true; return true;
} }
bool static JSObject *
createBufferWithSizeAndCount(JSContext *cx, uint32 size, uint32 count) createBufferWithSizeAndCount(JSContext *cx, uint32 count)
{ {
JS_ASSERT(size != 0); size_t size = sizeof(NativeType);
if (size != 0 && count >= INT32_MAX / size) { if (size != 0 && count >= INT32_MAX / size) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_NEED_DIET, "size and count"); JSMSG_NEED_DIET, "size and count");
@ -1333,30 +1334,7 @@ class TypedArrayTemplate
} }
int32 bytelen = size * count; int32 bytelen = size * count;
if (!createBufferWithByteLength(cx, bytelen)) return ArrayBuffer::create(cx, bytelen);
return false;
length = count;
return true;
}
bool
createBufferWithByteLength(JSContext *cx, int32 bytes)
{
Value arg = Int32Value(bytes), rval;
if (!ArrayBuffer::create(cx, 1, &arg, &rval))
return false;
JSObject *obj = &rval.toObject();
bufferJS = obj;
buffer = ArrayBuffer::fromJSObject(obj);
byteOffset = 0;
byteLength = bytes;
data = buffer->data;
return true;
} }
}; };
@ -1650,42 +1628,39 @@ js_IsTypedArray(JSObject *obj)
JS_FRIEND_API(JSObject *) JS_FRIEND_API(JSObject *)
js_CreateArrayBuffer(JSContext *cx, jsuint nbytes) js_CreateArrayBuffer(JSContext *cx, jsuint nbytes)
{ {
Value arg = NumberValue(nbytes), rval; return ArrayBuffer::create(cx, nbytes);
if (!ArrayBuffer::create(cx, 1, &arg, &rval))
return NULL;
return &rval.toObject();
} }
static inline JSBool static inline JSObject *
TypedArrayConstruct(JSContext *cx, jsint atype, uintN argc, Value *argv, Value *rv) TypedArrayConstruct(JSContext *cx, jsint atype, uintN argc, Value *argv)
{ {
switch (atype) { switch (atype) {
case TypedArray::TYPE_INT8: case TypedArray::TYPE_INT8:
return Int8Array::create(cx, argc, argv, rv); return Int8Array::create(cx, argc, argv);
case TypedArray::TYPE_UINT8: case TypedArray::TYPE_UINT8:
return Uint8Array::create(cx, argc, argv, rv); return Uint8Array::create(cx, argc, argv);
case TypedArray::TYPE_INT16: case TypedArray::TYPE_INT16:
return Int16Array::create(cx, argc, argv, rv); return Int16Array::create(cx, argc, argv);
case TypedArray::TYPE_UINT16: case TypedArray::TYPE_UINT16:
return Uint16Array::create(cx, argc, argv, rv); return Uint16Array::create(cx, argc, argv);
case TypedArray::TYPE_INT32: case TypedArray::TYPE_INT32:
return Int32Array::create(cx, argc, argv, rv); return Int32Array::create(cx, argc, argv);
case TypedArray::TYPE_UINT32: case TypedArray::TYPE_UINT32:
return Uint32Array::create(cx, argc, argv, rv); return Uint32Array::create(cx, argc, argv);
case TypedArray::TYPE_FLOAT32: case TypedArray::TYPE_FLOAT32:
return Float32Array::create(cx, argc, argv, rv); return Float32Array::create(cx, argc, argv);
case TypedArray::TYPE_FLOAT64: case TypedArray::TYPE_FLOAT64:
return Float64Array::create(cx, argc, argv, rv); return Float64Array::create(cx, argc, argv);
case TypedArray::TYPE_UINT8_CLAMPED: case TypedArray::TYPE_UINT8_CLAMPED:
return Uint8ClampedArray::create(cx, argc, argv, rv); return Uint8ClampedArray::create(cx, argc, argv);
default: default:
JS_NOT_REACHED("shouldn't have gotten here"); JS_NOT_REACHED("shouldn't have gotten here");
@ -1698,15 +1673,8 @@ js_CreateTypedArray(JSContext *cx, jsint atype, jsuint nelements)
{ {
JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX); JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX);
Value vals[2]; Value nelems = Int32Value(nelements);
vals[0].setInt32(nelements); return TypedArrayConstruct(cx, atype, 1, &nelems);
vals[1].setUndefined();
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(vals), vals);
if (!TypedArrayConstruct(cx, atype, 1, &vals[0], &vals[1]))
return NULL;
return &vals[1].toObject();
} }
JS_FRIEND_API(JSObject *) JS_FRIEND_API(JSObject *)
@ -1714,15 +1682,8 @@ js_CreateTypedArrayWithArray(JSContext *cx, jsint atype, JSObject *arrayArg)
{ {
JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX); JS_ASSERT(atype >= 0 && atype < TypedArray::TYPE_MAX);
Value vals[2]; Value arrval = ObjectValue(*arrayArg);
vals[0].setObject(*arrayArg); return TypedArrayConstruct(cx, atype, 1, &arrval);
vals[1].setUndefined();
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(vals), vals);
if (!TypedArrayConstruct(cx, atype, 1, &vals[0], &vals[1]))
return NULL;
return &vals[1].toObject();
} }
JS_FRIEND_API(JSObject *) JS_FRIEND_API(JSObject *)
@ -1737,7 +1698,6 @@ js_CreateTypedArrayWithBuffer(JSContext *cx, jsint atype, JSObject *bufArg,
int argc = 1; int argc = 1;
vals[0].setObject(*bufArg); vals[0].setObject(*bufArg);
vals[3].setUndefined();
if (byteoffset >= 0) { if (byteoffset >= 0) {
vals[argc].setInt32(byteoffset); vals[argc].setInt32(byteoffset);
@ -1750,10 +1710,7 @@ js_CreateTypedArrayWithBuffer(JSContext *cx, jsint atype, JSObject *bufArg,
} }
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(vals), vals); AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(vals), vals);
if (!TypedArrayConstruct(cx, atype, argc, &vals[0], &vals[3])) return TypedArrayConstruct(cx, atype, argc, &vals[0]);
return NULL;
return &vals[3].toObject();
} }
JS_FRIEND_API(JSBool) JS_FRIEND_API(JSBool)

Просмотреть файл

@ -64,7 +64,7 @@ struct JS_FRIEND_API(ArrayBuffer) {
static JSBool class_constructor(JSContext *cx, uintN argc, Value *vp); static JSBool class_constructor(JSContext *cx, uintN argc, Value *vp);
static bool create(JSContext *cx, uintN argc, Value *argv, Value *rval); static JSObject *create(JSContext *cx, int32 nbytes);
static ArrayBuffer *fromJSObject(JSObject *obj); static ArrayBuffer *fromJSObject(JSObject *obj);