const char* name,
ElementsKind elements_kind);
bool InstallNatives();
+
+ void InstallTypedArray(const char* name);
bool InstallExperimentalNatives();
void InstallBuiltinFunctionIds();
void InstallJSFunctionResultCaches();
}
+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());
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) {
// 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
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: \
}
+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());
}
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)
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:
CAST_ACCESSOR(Code)
CAST_ACCESSOR(JSArray)
CAST_ACCESSOR(JSArrayBuffer)
+CAST_ACCESSOR(JSTypedArray)
CAST_ACCESSOR(JSRegExp)
CAST_ACCESSOR(JSProxy)
CAST_ACCESSOR(JSFunctionProxy)
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)
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); \
}
+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()));
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);
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:
// - JSObject
// - JSArray
// - JSArrayBuffer
+// - JSTypedArray
// - JSSet
// - JSMap
// - JSWeakMap
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) \
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,
V(Boolean) \
V(JSArray) \
V(JSArrayBuffer) \
+ V(JSTypedArray) \
V(JSProxy) \
V(JSFunctionProxy) \
V(JSSet) \
};
+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.
#include "string-search.h"
#include "stub-cache.h"
#include "uri.h"
+#include "v8conversions.h"
#include "v8threads.h"
#include "vm-state-inl.h"
}
-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) {
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)
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);
}
+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);
F(NumberToExponential, 2, 1) \
F(NumberToPrecision, 2, 1)
+
#define RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \
/* Reflection */ \
F(FunctionSetInstanceClassName, 2, 1) \
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) \
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);
}
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);
+
// 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_
// Flags: --harmony-typed-arrays
+// ArrayBuffer
+
function TestByteLength(param, expectedByteLength) {
var ab = new __ArrayBuffer(param);
assertSame(expectedByteLength, ab.byteLength);
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);
}
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
}
TestArbitrary(new __ArrayBuffer(256));
-
// Test direct constructor call
assertTrue(__ArrayBuffer() instanceof __ArrayBuffer);