Commit c1a19275 authored by dslomov@chromium.org's avatar dslomov@chromium.org

First cut at impementing ES6 TypedArrays in V8.

BUG=

Review URL: https://codereview.chromium.org/13975012

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14285 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 266d2e63
......@@ -199,6 +199,8 @@ class Genesis BASE_EMBEDDED {
const char* name,
ElementsKind elements_kind);
bool InstallNatives();
void InstallTypedArray(const char* name);
bool InstallExperimentalNatives();
void InstallBuiltinFunctionIds();
void InstallJSFunctionResultCaches();
......@@ -1258,6 +1260,14 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
}
void Genesis::InstallTypedArray(const char* name) {
Handle<JSObject> global = Handle<JSObject>(native_context()->global_object());
InstallFunction(global, name, JS_TYPED_ARRAY_TYPE,
JSTypedArray::kSize, isolate()->initial_object_prototype(),
Builtins::kIllegal, true);
}
void Genesis::InitializeExperimentalGlobal() {
Handle<JSObject> global = Handle<JSObject>(native_context()->global_object());
......@@ -1298,6 +1308,17 @@ void Genesis::InitializeExperimentalGlobal() {
isolate()->initial_object_prototype(),
Builtins::kIllegal, true);
}
{
// -- T y p e d A r r a y s
InstallTypedArray("__Int8Array");
InstallTypedArray("__Uint8Array");
InstallTypedArray("__Int16Array");
InstallTypedArray("__Uint16Array");
InstallTypedArray("__Int32Array");
InstallTypedArray("__Uint32Array");
InstallTypedArray("__Float32Array");
InstallTypedArray("__Float64Array");
}
}
if (FLAG_harmony_generators) {
......
......@@ -102,6 +102,9 @@ var kMessages = {
// RangeError
invalid_array_length: ["Invalid array length"],
invalid_array_buffer_length: ["Invalid array buffer length"],
invalid_typed_array_offset: ["Start offset is too large"],
invalid_typed_array_length: ["Length is too large"],
invalid_typed_array_alignment: ["%0", "of", "%1", "should be a multiple of", "%3"],
stack_overflow: ["Maximum call stack size exceeded"],
invalid_time_value: ["Invalid time value"],
// SyntaxError
......
......@@ -201,6 +201,9 @@ void HeapObject::HeapObjectVerify() {
case JS_ARRAY_BUFFER_TYPE:
JSArrayBuffer::cast(this)->JSArrayBufferVerify();
break;
case JS_TYPED_ARRAY_TYPE:
JSTypedArray::cast(this)->JSTypedArrayVerify();
break;
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: \
......@@ -738,6 +741,28 @@ void JSArrayBuffer::JSArrayBufferVerify() {
}
void JSTypedArray::JSTypedArrayVerify() {
CHECK(IsJSTypedArray());
JSObjectVerify();
VerifyPointer(buffer());
CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined());
VerifyPointer(byte_offset());
CHECK(byte_offset()->IsSmi() || byte_offset()->IsHeapNumber()
|| byte_offset()->IsUndefined());
VerifyPointer(byte_length());
CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber()
|| byte_length()->IsUndefined());
VerifyPointer(length());
CHECK(length()->IsSmi() || length()->IsHeapNumber()
|| length()->IsUndefined());
VerifyPointer(elements());
}
void Foreign::ForeignVerify() {
CHECK(IsForeign());
}
......
......@@ -676,6 +676,7 @@ bool Object::IsBoolean() {
TYPE_CHECKER(JSArray, JS_ARRAY_TYPE)
TYPE_CHECKER(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE)
TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
......@@ -1605,6 +1606,8 @@ int JSObject::GetHeaderSize() {
return JSArray::kSize;
case JS_ARRAY_BUFFER_TYPE:
return JSArrayBuffer::kSize;
case JS_TYPED_ARRAY_TYPE:
return JSTypedArray::kSize;
case JS_SET_TYPE:
return JSSet::kSize;
case JS_MAP_TYPE:
......@@ -2492,6 +2495,7 @@ CAST_ACCESSOR(JSBuiltinsObject)
CAST_ACCESSOR(Code)
CAST_ACCESSOR(JSArray)
CAST_ACCESSOR(JSArrayBuffer)
CAST_ACCESSOR(JSTypedArray)
CAST_ACCESSOR(JSRegExp)
CAST_ACCESSOR(JSProxy)
CAST_ACCESSOR(JSFunctionProxy)
......@@ -5207,6 +5211,12 @@ void JSArrayBuffer::set_backing_store(void* value, WriteBarrierMode mode) {
ACCESSORS(JSArrayBuffer, byte_length, Object, kByteLengthOffset)
ACCESSORS(JSTypedArray, buffer, Object, kBufferOffset)
ACCESSORS(JSTypedArray, byte_offset, Object, kByteOffsetOffset)
ACCESSORS(JSTypedArray, byte_length, Object, kByteLengthOffset)
ACCESSORS(JSTypedArray, length, Object, kLengthOffset)
ACCESSORS(JSRegExp, data, Object, kDataOffset)
......
......@@ -187,6 +187,8 @@ void HeapObject::HeapObjectPrint(FILE* out) {
break;
case JS_ARRAY_BUFFER_TYPE:
JSArrayBuffer::cast(this)->JSArrayBufferPrint(out);
case JS_TYPED_ARRAY_TYPE:
JSTypedArray::cast(this)->JSTypedArrayPrint(out);
#define MAKE_STRUCT_CASE(NAME, Name, name) \
case NAME##_TYPE: \
Name::cast(this)->Name##Print(out); \
......@@ -809,6 +811,22 @@ void JSArrayBuffer::JSArrayBufferPrint(FILE* out) {
}
void JSTypedArray::JSTypedArrayPrint(FILE* out) {
HeapObject::PrintHeader(out, "JSTypedArray");
PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
PrintF(out, " - buffer =");
buffer()->ShortPrint(out);
PrintF(out, "\n - byte_offset = ");
byte_offset()->ShortPrint(out);
PrintF(out, "\n - byte_length = ");
byte_length()->ShortPrint(out);
PrintF(out, " - length = ");
length()->ShortPrint(out);
PrintF("\n");
PrintElements(out);
}
void JSFunction::JSFunctionPrint(FILE* out) {
HeapObject::PrintHeader(out, "Function");
PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
......
......@@ -146,6 +146,7 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
case JS_BUILTINS_OBJECT_TYPE:
case JS_MESSAGE_OBJECT_TYPE:
case JS_ARRAY_BUFFER_TYPE:
case JS_TYPED_ARRAY_TYPE:
return GetVisitorIdForSize(kVisitJSObject,
kVisitJSObjectGeneric,
instance_size);
......
......@@ -1556,6 +1556,7 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case JS_DATE_TYPE:
case JS_ARRAY_TYPE:
case JS_ARRAY_BUFFER_TYPE:
case JS_TYPED_ARRAY_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
case JS_WEAK_MAP_TYPE:
......
......@@ -57,6 +57,7 @@
// - JSObject
// - JSArray
// - JSArrayBuffer
// - JSTypedArray
// - JSSet
// - JSMap
// - JSWeakMap
......@@ -403,6 +404,7 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
V(JS_GLOBAL_PROXY_TYPE) \
V(JS_ARRAY_TYPE) \
V(JS_ARRAY_BUFFER_TYPE) \
V(JS_TYPED_ARRAY_TYPE) \
V(JS_PROXY_TYPE) \
V(JS_WEAK_MAP_TYPE) \
V(JS_REGEXP_TYPE) \
......@@ -735,6 +737,7 @@ enum InstanceType {
JS_GLOBAL_PROXY_TYPE,
JS_ARRAY_TYPE,
JS_ARRAY_BUFFER_TYPE,
JS_TYPED_ARRAY_TYPE,
JS_SET_TYPE,
JS_MAP_TYPE,
JS_WEAK_MAP_TYPE,
......@@ -982,6 +985,7 @@ class MaybeObject BASE_EMBEDDED {
V(Boolean) \
V(JSArray) \
V(JSArrayBuffer) \
V(JSTypedArray) \
V(JSProxy) \
V(JSFunctionProxy) \
V(JSSet) \
......@@ -8559,6 +8563,38 @@ class JSArrayBuffer: public JSObject {
};
class JSTypedArray: public JSObject {
public:
// [buffer]: ArrayBuffer that this typed array views.
DECL_ACCESSORS(buffer, Object)
// [byte_length]: offset of typed array in bytes.
DECL_ACCESSORS(byte_offset, Object)
// [byte_length]: length of typed array in bytes.
DECL_ACCESSORS(byte_length, Object)
// [length]: length of typed array in elements.
DECL_ACCESSORS(length, Object)
// Casting.
static inline JSTypedArray* cast(Object* obj);
// Dispatched behavior.
DECLARE_PRINTER(JSTypedArray)
DECLARE_VERIFIER(JSTypedArray)
static const int kBufferOffset = JSObject::kHeaderSize;
static const int kByteOffsetOffset = kBufferOffset + kPointerSize;
static const int kByteLengthOffset = kByteOffsetOffset + kPointerSize;
static const int kLengthOffset = kByteLengthOffset + kPointerSize;
static const int kSize = kLengthOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSTypedArray);
};
// Foreign describes objects pointing from JavaScript to C structures.
// Since they cannot contain references to JS HeapObjects they can be
// placed in old_data_space.
......
......@@ -61,6 +61,7 @@
#include "string-search.h"
#include "stub-cache.h"
#include "uri.h"
#include "v8conversions.h"
#include "v8threads.h"
#include "vm-state-inl.h"
......@@ -638,19 +639,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
}
static size_t ArrayBufferAllocatedLength(Isolate* isolate,
JSArrayBuffer* buffer) {
NoHandleAllocation hc(isolate);
Object* byte_length = buffer->byte_length();
if (byte_length->IsSmi()) {
return Smi::cast(byte_length)->value();
} else {
double value = HeapNumber::cast(byte_length)->value();
return static_cast<size_t>(value);
}
}
static void ArrayBufferWeakCallback(v8::Isolate* external_isolate,
Persistent<Value> object,
void* data) {
......@@ -658,8 +646,8 @@ static void ArrayBufferWeakCallback(v8::Isolate* external_isolate,
HandleScope scope(isolate);
Handle<Object> internal_object = Utils::OpenHandle(*object);
size_t allocated_length = ArrayBufferAllocatedLength(
isolate, JSArrayBuffer::cast(*internal_object));
size_t allocated_length = NumberToSize(
isolate, JSArrayBuffer::cast(*internal_object)->byte_length());
isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
-static_cast<intptr_t>(allocated_length));
if (data != NULL)
......@@ -744,12 +732,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
CONVERT_DOUBLE_ARG_CHECKED(first, 2);
size_t start = static_cast<size_t>(first);
size_t target_length = ArrayBufferAllocatedLength(isolate, *target);
size_t target_length = NumberToSize(isolate, target->byte_length());
if (target_length == 0)
return isolate->heap()->undefined_value();
ASSERT(ArrayBufferAllocatedLength(isolate, *source) - target_length >= start);
ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start);
uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
CopyBytes(target_data, source_data + start, target_length);
......@@ -757,6 +745,114 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
}
enum TypedArrayId {
// arrayIds below should be synchromized with typedarray.js natives.
ARRAY_ID_UINT8 = 1,
ARRAY_ID_INT8 = 2,
ARRAY_ID_UINT16 = 3,
ARRAY_ID_INT16 = 4,
ARRAY_ID_UINT32 = 5,
ARRAY_ID_INT32 = 6,
ARRAY_ID_FLOAT32 = 7,
ARRAY_ID_FLOAT64 = 8
};
RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 5);
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
CONVERT_SMI_ARG_CHECKED(arrayId, 1);
CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2);
CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
ExternalArrayType arrayType;
ElementsKind elementsKind;
size_t elementSize;
switch (arrayId) {
case ARRAY_ID_UINT8:
elementsKind = EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
arrayType = kExternalUnsignedByteArray;
elementSize = 1;
break;
case ARRAY_ID_INT8:
elementsKind = EXTERNAL_BYTE_ELEMENTS;
arrayType = kExternalByteArray;
elementSize = 1;
break;
case ARRAY_ID_UINT16:
elementsKind = EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
arrayType = kExternalUnsignedShortArray;
elementSize = 2;
break;
case ARRAY_ID_INT16:
elementsKind = EXTERNAL_SHORT_ELEMENTS;
arrayType = kExternalShortArray;
elementSize = 2;
break;
case ARRAY_ID_UINT32:
elementsKind = EXTERNAL_UNSIGNED_INT_ELEMENTS;
arrayType = kExternalUnsignedIntArray;
elementSize = 4;
break;
case ARRAY_ID_INT32:
elementsKind = EXTERNAL_INT_ELEMENTS;
arrayType = kExternalIntArray;
elementSize = 4;
break;
case ARRAY_ID_FLOAT32:
elementsKind = EXTERNAL_FLOAT_ELEMENTS;
arrayType = kExternalFloatArray;
elementSize = 4;
break;
case ARRAY_ID_FLOAT64:
elementsKind = EXTERNAL_DOUBLE_ELEMENTS;
arrayType = kExternalDoubleArray;
elementSize = 8;
break;
default:
UNREACHABLE();
}
holder->set_buffer(*buffer);
holder->set_byte_offset(*byte_offset_object);
holder->set_byte_length(*byte_length_object);
size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
size_t byte_length = NumberToSize(isolate, *byte_length_object);
ASSERT(byte_length % elementSize == 0);
size_t length = byte_length / elementSize;
holder->set_length(
*isolate->factory()->NewNumber(static_cast<double>(length)));
Handle<ExternalArray> elements =
isolate->factory()->NewExternalArray(
length, arrayType,
static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
Handle<Map> map =
isolate->factory()->GetElementsTransitionMap(holder, elementsKind);
holder->set_map(*map);
holder->set_elements(*elements);
return isolate->heap()->undefined_value();
}
#define TYPED_ARRAY_GETTER(getter, accessor) \
RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) { \
HandleScope scope(isolate); \
ASSERT(args.length() == 1); \
CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0); \
return holder->accessor(); \
}
TYPED_ARRAY_GETTER(Buffer, buffer)
TYPED_ARRAY_GETTER(ByteLength, byte_length)
TYPED_ARRAY_GETTER(ByteOffset, byte_offset)
TYPED_ARRAY_GETTER(Length, length)
#undef TYPED_ARRAY_GETTER
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
......
......@@ -219,6 +219,7 @@ namespace internal {
F(NumberToExponential, 2, 1) \
F(NumberToPrecision, 2, 1)
#define RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \
/* Reflection */ \
F(FunctionSetInstanceClassName, 2, 1) \
......@@ -350,6 +351,12 @@ namespace internal {
F(ArrayBufferGetByteLength, 1, 1)\
F(ArrayBufferSliceImpl, 3, 1) \
\
F(TypedArrayInitialize, 5, 1) \
F(TypedArrayGetBuffer, 1, 1) \
F(TypedArrayGetByteLength, 1, 1) \
F(TypedArrayGetByteOffset, 1, 1) \
F(TypedArrayGetLength, 1, 1) \
\
/* Statements */ \
F(NewClosure, 3, 1) \
F(NewObject, 1, 1) \
......
......@@ -82,14 +82,74 @@ function ArrayBufferSlice(start, end) {
return result;
}
// --------------- Typed Arrays ---------------------
function CreateTypedArrayConstructor(name, elementSize, arrayId, constructor) {
return function (buffer, byteOffset, length) {
if (%_IsConstructCall()) {
if (!IS_ARRAYBUFFER(buffer)) {
throw MakeTypeError("Type error!");
}
var offset = IS_UNDEFINED(byteOffset)
? 0 : offset = TO_POSITIVE_INTEGER(byteOffset);
if (offset % elementSize !== 0) {
throw MakeRangeError("invalid_typed_array_alignment",
"start offset", name, elementSize);
}
var bufferByteLength = %ArrayBufferGetByteLength(buffer);
if (offset >= bufferByteLength) {
throw MakeRangeError("invalid_typed_array_offset");
}
var newByteLength;
var newLength;
if (IS_UNDEFINED(length)) {
if (bufferByteLength % elementSize !== 0) {
throw MakeRangeError("invalid_typed_array_alignment",
"byte length", name, elementSize);
}
newByteLength = bufferByteLength - offset;
newLength = newByteLength / elementSize;
} else {
var newLength = TO_POSITIVE_INTEGER(length);
newByteLength = newLength * elementSize;
}
if (newByteLength > bufferByteLength) {
throw MakeRangeError("invalid_typed_array_length");
}
%TypedArrayInitialize(this, arrayId, buffer, offset, newByteLength);
} else {
return new constructor(buffer, byteOffset, length);
}
}
}
function TypedArrayGetBuffer() {
return %TypedArrayGetBuffer(this);
}
function TypedArrayGetByteLength() {
return %TypedArrayGetByteLength(this);
}
function TypedArrayGetByteOffset() {
return %TypedArrayGetByteOffset(this);
}
function TypedArrayGetLength() {
return %TypedArrayGetLength(this);
}
// -------------------------------------------------------------------
function SetUpArrayBuffer() {
%CheckIsBootstrapping();
// Set up the Uint16Array constructor function.
// Set up the ArrayBuffer constructor function.
%SetCode($ArrayBuffer, ArrayBufferConstructor);
%FunctionSetPrototype($ArrayBuffer, new $Object());
// Set up the constructor property on the ArrayBuffer prototype object.
%SetProperty($ArrayBuffer.prototype, "constructor", $ArrayBuffer, DONT_ENUM);
......@@ -102,3 +162,31 @@ function SetUpArrayBuffer() {
}
SetUpArrayBuffer();
function SetupTypedArray(arrayId, name, constructor, elementSize) {
var f = CreateTypedArrayConstructor(name, elementSize,
arrayId, constructor);
%SetCode(constructor, f);
%FunctionSetPrototype(constructor, new $Object());
%SetProperty(constructor.prototype,
"constructor", constructor, DONT_ENUM);
%SetProperty(constructor.prototype,
"BYTES_PER_ELEMENT", elementSize,
READ_ONLY | DONT_ENUM | DONT_DELETE);
InstallGetter(constructor.prototype, "buffer", TypedArrayGetBuffer);
InstallGetter(constructor.prototype, "byteOffset", TypedArrayGetByteOffset);
InstallGetter(constructor.prototype, "byteLength", TypedArrayGetByteLength);
InstallGetter(constructor.prototype, "length", TypedArrayGetLength);
}
// arrayIds below should be synchronized with Runtime_TypedArrayInitialize.
SetupTypedArray(1, "Uint8Array", global.__Uint8Array, 1);
SetupTypedArray(2, "Int8Array", global.__Int8Array, 1);
SetupTypedArray(3, "Uint16Array", global.__Uint16Array, 2);
SetupTypedArray(4, "Int16Array", global.__Int16Array, 2);
SetupTypedArray(5, "Uint32Array", global.__Uint32Array, 4);
SetupTypedArray(6, "Int32Array", global.__Int32Array, 4);
SetupTypedArray(7, "Float32Array", global.__Float32Array, 4);
SetupTypedArray(8, "Float64Array", global.__Float64Array, 8);
......@@ -55,6 +55,19 @@ double StringToDouble(UnicodeCache* unicode_cache,
// Converts a string into an integer.
double StringToInt(UnicodeCache* unicode_cache, String* str, int radix);
// Converts a number into size_t.
inline size_t NumberToSize(Isolate* isolate,
Object* number) {
NoHandleAllocation hc(isolate);
if (number->IsSmi()) {
return Smi::cast(number)->value();
} else {
ASSERT(number->IsHeapNumber());
double value = HeapNumber::cast(number)->value();
return static_cast<size_t>(value);
}
}
} } // namespace v8::internal
#endif // V8_V8CONVERSIONS_H_
......@@ -27,6 +27,8 @@
// Flags: --harmony-typed-arrays
// ArrayBuffer
function TestByteLength(param, expectedByteLength) {
var ab = new __ArrayBuffer(param);
assertSame(expectedByteLength, ab.byteLength);
......@@ -104,8 +106,98 @@ function TestArrayBufferSlice() {
TestArrayBufferSlice();
// Typed arrays
function TestTypedArray(proto, elementSize, typicalElement) {
var ab = new __ArrayBuffer(256*elementSize);
var a1 = new proto(ab, 128*elementSize, 128);
assertSame(ab, a1.buffer);
assertSame(elementSize, a1.BYTES_PER_ELEMENT);
assertSame(128, a1.length);
assertSame(128*elementSize, a1.byteLength);
assertSame(128*elementSize, a1.byteOffset);
var a2 = new proto(ab, 64*elementSize, 128);
assertSame(ab, a2.buffer);
assertSame(elementSize, a2.BYTES_PER_ELEMENT);
assertSame(128, a2.length);
assertSame(128*elementSize, a2.byteLength);
assertSame(64*elementSize, a2.byteOffset);
var a3 = new proto(ab, 192*elementSize);
assertSame(ab, a3.buffer);
assertSame(64, a3.length);
assertSame(64*elementSize, a3.byteLength);
assertSame(192*elementSize, a3.byteOffset);
var a4 = new proto(ab);
assertSame(ab, a4.buffer);
assertSame(256, a4.length);
assertSame(256*elementSize, a4.byteLength);
assertSame(0, a4.byteOffset);
var i;
for (i = 0; i < 128; i++) {
a1[i] = typicalElement;
}
for (i = 0; i < 128; i++) {
assertSame(typicalElement, a1[i]);
}
for (i = 0; i < 64; i++) {
assertSame(0, a2[i]);
}
for (i = 64; i < 128; i++) {
assertSame(typicalElement, a2[i]);
}
for (i = 0; i < 64; i++) {
assertSame(typicalElement, a3[i]);
}
for (i = 0; i < 128; i++) {
assertSame(0, a4[i]);
}
for (i = 128; i < 256; i++) {
assertSame(typicalElement, a4[i]);
}
assertThrows(function () { new proto(ab, 256*elementSize); }, RangeError);
if (elementSize !== 1) {
assertThrows(function() { new proto(ab, 128*elementSize - 1, 10); },
RangeError);
var unalignedArrayBuffer = new __ArrayBuffer(10*elementSize + 1);
var goodArray = new proto(unalignedArrayBuffer, 0, 10);
assertSame(10, goodArray.length);
assertSame(10*elementSize, goodArray.byteLength);
assertThrows(function() { new proto(unalignedArrayBuffer)}, RangeError);
assertThrows(function() { new proto(unalignedArrayBuffer, 5*elementSize)},
RangeError);
}
}
TestTypedArray(__Uint8Array, 1, 0xFF);
TestTypedArray(__Int8Array, 1, -0x7F);
TestTypedArray(__Uint16Array, 2, 0xFFFF);
TestTypedArray(__Int16Array, 2, -0x7FFF);
TestTypedArray(__Uint32Array, 4, 0xFFFFFFFF);
TestTypedArray(__Int32Array, 4, -0x7FFFFFFF);
TestTypedArray(__Float32Array, 4, 0.5);
TestTypedArray(__Float64Array, 8, 0.5);
// General tests for properties
// Test property attribute [[Enumerable]]
function TestEnumerable(func) {
function TestEnumerable(func, obj) {
function props(x) {
var array = [];
for (var p in x) array.push(p);
......@@ -113,9 +205,11 @@ function TestEnumerable(func) {
}
assertArrayEquals([], props(func));
assertArrayEquals([], props(func.prototype));
assertArrayEquals([], props(new func()));
if (obj)
assertArrayEquals([], props(obj));
}
TestEnumerable(__ArrayBuffer);
TestEnumerable(__ArrayBuffer, new __ArrayBuffer());
TestEnumerable(__Uint8Array);
// Test arbitrary properties on ArrayBuffer
......@@ -131,6 +225,5 @@ function TestArbitrary(m) {
}
TestArbitrary(new __ArrayBuffer(256));
// Test direct constructor call
assertTrue(__ArrayBuffer() instanceof __ArrayBuffer);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment