void TypedArray (const Wrapper* wrapper, Handle<Value> value, vector<void*>& natives) { void *buff = NULL; size_t byteLength = 0; if (value->IsObject()) { Handle<Object> obj = value->ToObject(); if (obj->HasIndexedPropertiesInExternalArrayData()) { buff = obj->GetIndexedPropertiesExternalArrayData(); byteLength = obj->GetIndexedPropertiesExternalArrayDataLength(); switch (obj->GetIndexedPropertiesExternalArrayDataType()) { case kExternalByteArray: case kExternalUnsignedByteArray: case kExternalPixelArray: break; case kExternalShortArray: case kExternalUnsignedShortArray: byteLength *= 2; break; case kExternalIntArray: case kExternalUnsignedIntArray: case kExternalFloatArray: byteLength *= 4; break; case kExternalDoubleArray: byteLength *= 8; break; } } else { buff = Get<void*>(value); } } PushBackWrapped(natives, buff); PushBackWrapped(natives, byteLength); }
Handle<Value> CreateExternalArray(const Arguments& args, ExternalArrayType type, size_t element_size) { TryCatch try_catch; ASSERT_PIN(element_size == 1 || element_size == 2 || element_size == 4 || element_size == 8, "CreateExternalArray"); // Currently, only the following constructors are supported: // TypedArray(unsigned long length) // TypedArray(ArrayBuffer buffer, // optional unsigned long byteOffset, // optional unsigned long length) Handle<Object> buffer; int32_t length; int32_t byteLength; int32_t byteOffset; int32_t bufferLength; if (args.Length() == 0) { return ThrowException( String::New("Array constructor must have at least one parameter.")); } if (args[0]->IsObject() && (!args[0]->ToObject()->GetHiddenValue(String::New(kArrayBufferMarkerPropName)).IsEmpty()) || (IS_BINARY(args[0]))) { if (!args[0]->ToObject()->GetHiddenValue(String::New(kArrayBufferMarkerPropName)).IsEmpty()) { buffer = args[0]->ToObject(); bufferLength = convertToUint(buffer->Get(String::New("byteLength")), &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); } else { buffer = CreateExternalArrayBuffer(args[0])->ToObject(); bufferLength = convertToUint(buffer->Get(String::New("byteLength")), &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); } if (args.Length() < 2 || args[1]->IsUndefined()) { byteOffset = 0; } else { byteOffset = convertToUint(args[1], &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); if (byteOffset > bufferLength) { return ThrowException(String::New("byteOffset out of bounds")); } if (byteOffset % element_size != 0) { return ThrowException( String::New("byteOffset must be multiple of element_size")); } } if (args.Length() < 3 || args[2]->IsUndefined()) { byteLength = bufferLength - byteOffset; length = byteLength / element_size; if (byteLength % element_size != 0) { return ThrowException( String::New("buffer size must be multiple of element_size")); } } else { length = convertToUint(args[2], &try_catch); if (try_catch.HasCaught()) return try_catch.Exception(); byteLength = length * element_size; if (byteOffset + byteLength > bufferLength) { return ThrowException(String::New("length out of bounds")); } } } else { length = convertToUint(args[0], &try_catch); byteLength = length * element_size; byteOffset = 0; Handle<Value> result = CreateExternalArrayBuffer(byteLength); if (!result->IsObject()) return result; buffer = result->ToObject(); } void* data = buffer->GetIndexedPropertiesExternalArrayData(); ASSERT_PIN(data != NULL, "CreateExternalArray data != NULL"); Handle<Object> array = Object::New(); array->SetIndexedPropertiesToExternalArrayData( static_cast<uint8_t*>(data) + byteOffset, type, length); array->Set(String::New("byteLength"), Int32::New(byteLength), ReadOnly); array->Set(String::New("byteOffset"), Int32::New(byteOffset), ReadOnly); array->Set(String::New("length"), Int32::New(length), ReadOnly); array->Set(String::New("BYTES_PER_ELEMENT"), Int32::New(element_size)); array->Set(String::New("buffer"), buffer, ReadOnly); return array; }