зеркало из https://github.com/mozilla/gecko-dev.git
[JAEGER] Merge from Tracemonkey.
This commit is contained in:
Коммит
ed5cb37cc3
|
@ -821,11 +821,8 @@ class TypedArrayTemplate
|
|||
static JSBool
|
||||
fun_slice(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
Value *argv;
|
||||
JSObject *obj;
|
||||
|
||||
argv = JS_ARGV(cx, vp);
|
||||
obj = ComputeThisFromVp(cx, vp);
|
||||
Value *argv = JS_ARGV(cx, vp);
|
||||
JSObject *obj = ComputeThisFromVp(cx, vp);
|
||||
|
||||
if (!InstanceOf(cx, obj, ThisTypeArray::fastClass(), vp+2))
|
||||
return false;
|
||||
|
@ -896,6 +893,86 @@ class TypedArrayTemplate
|
|||
return true;
|
||||
}
|
||||
|
||||
/* set(array[, offset]) */
|
||||
static JSBool
|
||||
fun_set(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
Value *argv = JS_ARGV(cx, vp);
|
||||
JSObject *obj = ComputeThisFromVp(cx, vp);
|
||||
|
||||
if (!InstanceOf(cx, obj, ThisTypeArray::fastClass(), vp+2))
|
||||
return false;
|
||||
|
||||
if (obj->getClass() != fastClass()) {
|
||||
// someone tried to apply this set() to the wrong class
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_INCOMPATIBLE_METHOD,
|
||||
fastClass()->name, "set", obj->getClass()->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
|
||||
if (!tarray)
|
||||
return true;
|
||||
|
||||
// these are the default values
|
||||
int32_t offset = 0;
|
||||
|
||||
if (argc > 1) {
|
||||
if (!ValueToInt32(cx, argv[1], &offset))
|
||||
return false;
|
||||
|
||||
if (offset < 0 || uint32_t(offset) > tarray->length) {
|
||||
// the given offset is bogus
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// first arg must be either a typed array or a JS array
|
||||
if (!argv[0].isObject()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject *arg0 = argv[0].toObjectOrNull();
|
||||
if (js_IsTypedArray(arg0)) {
|
||||
TypedArray *src = TypedArray::fromJSObject(arg0);
|
||||
if (!src ||
|
||||
src->length > tarray->length - offset)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
tarray->copyFrom(src, offset);
|
||||
} else if (arg0->wrappedObject(cx)->isArray()) {
|
||||
jsuint len;
|
||||
if (!js_GetLengthProperty(cx, arg0, &len))
|
||||
return false;
|
||||
|
||||
// avoid overflow; we know that offset <= length
|
||||
if (len > tarray->length - offset) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!tarray->copyFrom(cx, arg0, len, offset))
|
||||
return false;
|
||||
} else {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
vp->setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static ThisTypeArray *
|
||||
fromJSObject(JSObject *obj)
|
||||
{
|
||||
|
@ -930,9 +1007,9 @@ class TypedArrayTemplate
|
|||
|
||||
//printf ("Constructing with type %d other %p offset %d length %d\n", type, other, byteOffset, length);
|
||||
|
||||
if (JS_IsArrayObject(cx, other)) {
|
||||
if (other->wrappedObject(cx)->isArray()) {
|
||||
jsuint len;
|
||||
if (!JS_GetArrayLength(cx, other, &len))
|
||||
if (!js_GetLengthProperty(cx, other, &len))
|
||||
return false;
|
||||
if (!createBufferWithSizeAndCount(cx, sizeof(NativeType), len))
|
||||
return false;
|
||||
|
@ -946,8 +1023,7 @@ class TypedArrayTemplate
|
|||
|
||||
if (!createBufferWithSizeAndCount(cx, sizeof(NativeType), tarray->length))
|
||||
return false;
|
||||
if (!copyFrom(tarray))
|
||||
return false;
|
||||
copyFrom(tarray);
|
||||
} else if (other->getClass() == &ArrayBuffer::jsclass) {
|
||||
ArrayBuffer *abuf = ArrayBuffer::fromJSObject(other);
|
||||
|
||||
|
@ -1067,9 +1143,11 @@ class TypedArrayTemplate
|
|||
}
|
||||
|
||||
bool
|
||||
copyFrom(JSContext *cx, JSObject *ar, jsuint len)
|
||||
copyFrom(JSContext *cx, JSObject *ar, jsuint len, jsuint offset = 0)
|
||||
{
|
||||
NativeType *dest = static_cast<NativeType*>(data);
|
||||
JS_ASSERT(offset <= length);
|
||||
JS_ASSERT(len <= length - offset);
|
||||
NativeType *dest = static_cast<NativeType*>(data) + offset;
|
||||
|
||||
if (ar->isDenseArray() && ar->getDenseArrayCapacity() >= len) {
|
||||
JS_ASSERT(ar->getArrayLength() == len);
|
||||
|
@ -1092,63 +1170,71 @@ class TypedArrayTemplate
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
copyFrom(TypedArray *tarray)
|
||||
void
|
||||
copyFrom(TypedArray *tarray, jsuint offset = 0)
|
||||
{
|
||||
NativeType *dest = static_cast<NativeType*>(data);
|
||||
JS_ASSERT(offset <= length);
|
||||
JS_ASSERT(tarray->length <= length - offset);
|
||||
if (tarray->buffer == buffer) {
|
||||
copyFromWithOverlap(tarray, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
NativeType *dest = static_cast<NativeType*>(data) + offset;
|
||||
|
||||
if (tarray->type == type) {
|
||||
memcpy(dest, tarray->data, tarray->byteLength);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
uintN srclen = tarray->length;
|
||||
switch (tarray->type) {
|
||||
case TypedArray::TYPE_INT8: {
|
||||
int8 *src = static_cast<int8*>(tarray->data);
|
||||
for (uintN i = 0; i < length; ++i)
|
||||
for (uintN i = 0; i < srclen; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_UINT8:
|
||||
case TypedArray::TYPE_UINT8_CLAMPED: {
|
||||
uint8 *src = static_cast<uint8*>(tarray->data);
|
||||
for (uintN i = 0; i < length; ++i)
|
||||
for (uintN i = 0; i < srclen; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_INT16: {
|
||||
int16 *src = static_cast<int16*>(tarray->data);
|
||||
for (uintN i = 0; i < length; ++i)
|
||||
for (uintN i = 0; i < srclen; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_UINT16: {
|
||||
uint16 *src = static_cast<uint16*>(tarray->data);
|
||||
for (uintN i = 0; i < length; ++i)
|
||||
for (uintN i = 0; i < srclen; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_INT32: {
|
||||
int32 *src = static_cast<int32*>(tarray->data);
|
||||
for (uintN i = 0; i < length; ++i)
|
||||
for (uintN i = 0; i < srclen; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_UINT32: {
|
||||
uint32 *src = static_cast<uint32*>(tarray->data);
|
||||
for (uintN i = 0; i < length; ++i)
|
||||
for (uintN i = 0; i < srclen; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_FLOAT32: {
|
||||
float *src = static_cast<float*>(tarray->data);
|
||||
for (uintN i = 0; i < length; ++i)
|
||||
for (uintN i = 0; i < srclen; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_FLOAT64: {
|
||||
double *src = static_cast<double*>(tarray->data);
|
||||
for (uintN i = 0; i < length; ++i)
|
||||
for (uintN i = 0; i < srclen; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
|
@ -1156,8 +1242,81 @@ class TypedArrayTemplate
|
|||
JS_NOT_REACHED("copyFrom with a TypedArray of unknown type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
void
|
||||
copyFromWithOverlap(TypedArray *tarray, jsuint offset = 0)
|
||||
{
|
||||
JS_ASSERT(offset < length);
|
||||
|
||||
NativeType *dest = static_cast<NativeType*>(data) + offset;
|
||||
|
||||
if (tarray->type == type) {
|
||||
memmove(dest, tarray->data, tarray->byteLength);
|
||||
return;
|
||||
}
|
||||
|
||||
// We have to make a copy of the source array here, since
|
||||
// there's overlap, and we have to convert types.
|
||||
void *srcbuf = js_malloc(tarray->byteLength);
|
||||
memcpy(srcbuf, tarray->data, tarray->byteLength);
|
||||
|
||||
switch (tarray->type) {
|
||||
case TypedArray::TYPE_INT8: {
|
||||
int8 *src = (int8*) srcbuf;
|
||||
for (uintN i = 0; i < tarray->length; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_UINT8:
|
||||
case TypedArray::TYPE_UINT8_CLAMPED: {
|
||||
uint8 *src = (uint8*) srcbuf;
|
||||
for (uintN i = 0; i < tarray->length; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_INT16: {
|
||||
int16 *src = (int16*) srcbuf;
|
||||
for (uintN i = 0; i < tarray->length; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_UINT16: {
|
||||
uint16 *src = (uint16*) srcbuf;
|
||||
for (uintN i = 0; i < tarray->length; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_INT32: {
|
||||
int32 *src = (int32*) srcbuf;
|
||||
for (uintN i = 0; i < tarray->length; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_UINT32: {
|
||||
uint32 *src = (uint32*) srcbuf;
|
||||
for (uintN i = 0; i < tarray->length; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_FLOAT32: {
|
||||
float *src = (float*) srcbuf;
|
||||
for (uintN i = 0; i < tarray->length; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
case TypedArray::TYPE_FLOAT64: {
|
||||
double *src = (double*) srcbuf;
|
||||
for (uintN i = 0; i < tarray->length; ++i)
|
||||
*dest++ = NativeType(*src++);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
JS_NOT_REACHED("copyFromWithOverlap with a TypedArray of unknown type");
|
||||
break;
|
||||
}
|
||||
|
||||
js_free(srcbuf);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1325,6 +1484,7 @@ JSPropertySpec TypedArray::jsprops[] = {
|
|||
#define IMPL_TYPED_ARRAY_STATICS(_typedArray) \
|
||||
template<> JSFunctionSpec _typedArray::jsfuncs[] = { \
|
||||
JS_FN("slice", _typedArray::fun_slice, 2, 0), \
|
||||
JS_FN("set", _typedArray::fun_set, 2, 0), \
|
||||
JS_FS_END \
|
||||
}
|
||||
|
||||
|
|
|
@ -230,6 +230,73 @@ function test()
|
|||
check(function() !(a[3] == a[3]));
|
||||
check(function() a[4] == 1);
|
||||
|
||||
// test set()
|
||||
var empty = new Int32Array(0);
|
||||
a = new Int32Array(9);
|
||||
|
||||
empty.set([]);
|
||||
empty.set([], 0);
|
||||
|
||||
checkThrows(function() empty.set([1]));
|
||||
checkThrows(function() empty.set([1], 0));
|
||||
checkThrows(function() empty.set([1], 1));
|
||||
|
||||
a.set([]);
|
||||
a.set([], 3);
|
||||
a.set([], 9);
|
||||
|
||||
a.set(empty);
|
||||
a.set(empty, 3);
|
||||
a.set(empty, 9);
|
||||
a.set(Array.prototype);
|
||||
checkThrows(function() a.set(empty, 100));
|
||||
|
||||
checkThrows(function() a.set([1,2,3,4,5,6,7,8,9,10]));
|
||||
checkThrows(function() a.set([1,2,3,4,5,6,7,8,9,10], 0));
|
||||
checkThrows(function() a.set([1,2,3,4,5,6,7,8,9,10], 0x7fffffff));
|
||||
checkThrows(function() a.set([1,2,3,4,5,6,7,8,9,10], 0xffffffff));
|
||||
checkThrows(function() a.set([1,2,3,4,5,6], 6));
|
||||
|
||||
checkThrows(function() a.set(new Array(0x7fffffff)));
|
||||
checkThrows(function() a.set([1,2,3], 2147483647));
|
||||
|
||||
checkThrows(function() a.set(ArrayBuffer.prototype));
|
||||
checkThrows(function() a.set(UInt16Array.prototype));
|
||||
checkThrows(function() a.set(Int32Array.prototype));
|
||||
|
||||
a.set([1,2,3]);
|
||||
a.set([4,5,6], 3);
|
||||
check(function()
|
||||
a[0] == 1 && a[1] == 2 && a[2] == 3 &&
|
||||
a[3] == 4 && a[4] == 5 && a[5] == 6 &&
|
||||
a[6] == 0 && a[7] == 0 && a[8] == 0);
|
||||
|
||||
b = new Float32Array([7,8,9]);
|
||||
a.set(b, 0);
|
||||
a.set(b, 3);
|
||||
check(function()
|
||||
a[0] == 7 && a[1] == 8 && a[2] == 9 &&
|
||||
a[3] == 7 && a[4] == 8 && a[5] == 9 &&
|
||||
a[6] == 0 && a[7] == 0 && a[8] == 0);
|
||||
a.set(a.slice(0,3), 6);
|
||||
check(function()
|
||||
a[0] == 7 && a[1] == 8 && a[2] == 9 &&
|
||||
a[3] == 7 && a[4] == 8 && a[5] == 9 &&
|
||||
a[6] == 7 && a[7] == 8 && a[8] == 9);
|
||||
|
||||
a.set([1,2,3,4,5,6,7,8,9]);
|
||||
a.set(a.slice(0,6), 3);
|
||||
check(function()
|
||||
a[0] == 1 && a[1] == 2 && a[2] == 3 &&
|
||||
a[3] == 1 && a[4] == 2 && a[5] == 3 &&
|
||||
a[6] == 4 && a[7] == 5 && a[8] == 6);
|
||||
|
||||
a.set(a.slice(3,9), 0);
|
||||
check(function()
|
||||
a[0] == 1 && a[1] == 2 && a[2] == 3 &&
|
||||
a[3] == 4 && a[4] == 5 && a[5] == 6 &&
|
||||
a[6] == 4 && a[7] == 5 && a[8] == 6);
|
||||
|
||||
a = new ArrayBuffer(0x10);
|
||||
checkThrows(function() new Uint32Array(buffer, 4, 0x3FFFFFFF));
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче