зеркало из https://github.com/mozilla/gecko-dev.git
merge
This commit is contained in:
Коммит
0296432927
|
@ -123,16 +123,11 @@ NativeIterator::mark(JSTracer *trc)
|
|||
MarkObject(trc, obj, "obj");
|
||||
}
|
||||
|
||||
/*
|
||||
* Shared code to close iterator's state either through an explicit call or
|
||||
* when GC detects that the iterator is no longer reachable.
|
||||
*/
|
||||
static void
|
||||
iterator_finalize(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(obj->getClass() == &js_IteratorClass);
|
||||
|
||||
/* Avoid double work if the iterator was closed by JSOP_ENDITER. */
|
||||
NativeIterator *ni = obj->getNativeIterator();
|
||||
if (ni) {
|
||||
cx->free(ni);
|
||||
|
@ -811,8 +806,6 @@ js_CloseIterator(JSContext *cx, JSObject *obj)
|
|||
ni->props_cursor = ni->props_array;
|
||||
ni->next = *hp;
|
||||
*hp = obj;
|
||||
} else {
|
||||
iterator_finalize(cx, obj);
|
||||
}
|
||||
}
|
||||
#if JS_HAS_GENERATORS
|
||||
|
|
|
@ -126,15 +126,12 @@ ArrayBuffer::create(JSContext *cx, JSObject *obj,
|
|||
rval->setObject(*obj);
|
||||
}
|
||||
|
||||
if (argc == 0) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return false;
|
||||
int32_t nbytes = 0;
|
||||
if (argc > 0) {
|
||||
if (!ValueToECMAInt32(cx, argv[0], &nbytes))
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t nbytes;
|
||||
if (!ValueToECMAInt32(cx, argv[0], &nbytes))
|
||||
return false;
|
||||
if (nbytes < 0) {
|
||||
/*
|
||||
* We're just not going to support arrays that are bigger than what will fit
|
||||
|
@ -745,20 +742,17 @@ class TypedArrayTemplate
|
|||
|
||||
ThisTypeArray *tarray = 0;
|
||||
|
||||
// must have at least one arg
|
||||
if (argc == 0) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
// figure out the type of the first argument;
|
||||
// no args is treated like an int arg of 0.
|
||||
if (argc == 0 || argv[0].isInt32()) {
|
||||
int32 len = 0;
|
||||
|
||||
if (argc != 0)
|
||||
len = argv[0].toInt32();
|
||||
|
||||
// figure out the type of the first argument
|
||||
if (argv[0].isInt32()) {
|
||||
int32 len = argv[0].toInt32();
|
||||
if (len < 0) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_ARRAY_LENGTH);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -827,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;
|
||||
|
@ -902,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)
|
||||
{
|
||||
|
@ -936,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;
|
||||
|
@ -952,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);
|
||||
|
||||
|
@ -1073,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);
|
||||
|
@ -1098,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;
|
||||
}
|
||||
|
@ -1162,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
|
||||
|
@ -1331,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 \
|
||||
}
|
||||
|
||||
|
|
|
@ -96,10 +96,25 @@ function test()
|
|||
check(function() (new Int32Array(zerobuf)).length == 0);
|
||||
checkThrows(function() new Int32Array(zerobuf, 1));
|
||||
|
||||
var zerobuf2 = new ArrayBuffer();
|
||||
check(function() zerobuf2.byteLength == 0);
|
||||
|
||||
checkThrows(function() new ArrayBuffer(-100));
|
||||
// this is using js_ValueToECMAUInt32, which is giving 0 for "abc"
|
||||
checkThrows(function() new ArrayBuffer("abc"), TODO);
|
||||
|
||||
var zeroarray = new Int32Array(0);
|
||||
check(function() zeroarray.length == 0);
|
||||
check(function() zeroarray.byteLength == 0);
|
||||
check(function() zeroarray.buffer);
|
||||
check(function() zeroarray.buffer.byteLength == 0);
|
||||
|
||||
var zeroarray2 = new Int32Array();
|
||||
check(function() zeroarray2.length == 0);
|
||||
check(function() zeroarray2.byteLength == 0);
|
||||
check(function() zeroarray2.buffer);
|
||||
check(function() zeroarray2.buffer.byteLength == 0);
|
||||
|
||||
var a = new Int32Array(20);
|
||||
check(function() a);
|
||||
check(function() a.length == 20);
|
||||
|
@ -215,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));
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче