V8ArrayBufferViewCustom.h [plain text]
#ifndef V8ArrayBufferViewCustom_h
#define V8ArrayBufferViewCustom_h
#include <wtf/ArrayBuffer.h>
#include "ExceptionCode.h"
#include "V8ArrayBuffer.h"
#include "V8Binding.h"
#include "V8Proxy.h"
namespace WebCore {
bool fastSetInstalled(v8::Handle<v8::Object> array);
void installFastSet(v8::Handle<v8::Object> array);
void copyElements(v8::Handle<v8::Object> destArray, v8::Handle<v8::Object> srcArray, uint32_t offset);
template<class ArrayClass, class ElementType>
v8::Handle<v8::Value> constructWebGLArrayWithArrayBufferArgument(const v8::Arguments& args, WrapperTypeInfo* type, v8::ExternalArrayType arrayType, bool hasIndexer)
{
ArrayBuffer* buf = V8ArrayBuffer::toNative(args[0]->ToObject());
if (!buf)
return throwError("Could not convert argument 0 to a ArrayBuffer");
bool ok;
uint32_t offset = 0;
int argLen = args.Length();
if (argLen > 1) {
offset = toUInt32(args[1], ok);
if (!ok)
return throwError("Could not convert argument 1 to a number");
}
uint32_t length = 0;
if (argLen > 2) {
length = toUInt32(args[2], ok);
if (!ok)
return throwError("Could not convert argument 2 to a number");
} else {
if ((buf->byteLength() - offset) % sizeof(ElementType))
return throwError("ArrayBuffer length minus the byteOffset is not a multiple of the element size.", V8Proxy::RangeError);
length = (buf->byteLength() - offset) / sizeof(ElementType);
}
RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length);
if (!array) {
V8Proxy::setDOMException(INDEX_SIZE_ERR, args.GetIsolate());
return notHandledByInterceptor();
}
V8DOMWrapper::setDOMWrapper(args.Holder(), type, array.get());
if (hasIndexer)
args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddress(), arrayType, array.get()->length());
v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::New(args.Holder());
wrapper.MarkIndependent();
V8DOMWrapper::setJSWrapperForDOMObject(array.release(), wrapper);
return args.Holder();
}
template<class ArrayClass, class ElementType>
v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args, WrapperTypeInfo* type, v8::ExternalArrayType arrayType)
{
if (!args.IsConstructCall())
return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError);
if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
return args.Holder();
int argLen = args.Length();
if (!argLen) {
RefPtr<ArrayClass> array = ArrayClass::create(0);
V8DOMWrapper::setDOMWrapper(args.Holder(), type, array.get());
v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::New(args.Holder());
wrapper.MarkIndependent();
V8DOMWrapper::setJSWrapperForDOMObject(array.release(), wrapper);
return args.Holder();
}
if (args[0]->IsNull()) {
return V8Proxy::throwError(V8Proxy::TypeError, "Type error");
}
if (V8ArrayBuffer::HasInstance(args[0]))
return constructWebGLArrayWithArrayBufferArgument<ArrayClass, ElementType>(args, type, arrayType, true);
uint32_t len = 0;
v8::Handle<v8::Object> srcArray;
bool doInstantiation = false;
if (args[0]->IsObject()) {
srcArray = args[0]->ToObject();
if (srcArray.IsEmpty())
return throwError("Could not convert argument 0 to an array");
len = toUInt32(srcArray->Get(v8::String::New("length")));
doInstantiation = true;
} else {
bool ok = false;
int32_t tempLength = toInt32(args[0], ok); if (ok && tempLength >= 0) {
len = static_cast<uint32_t>(tempLength);
doInstantiation = true;
}
}
RefPtr<ArrayClass> array;
if (doInstantiation)
array = ArrayClass::create(len);
if (!array.get())
return throwError("ArrayBufferView size is not a small enough positive integer.", V8Proxy::RangeError);
V8DOMWrapper::setDOMWrapper(args.Holder(), type, array.get());
args.Holder()->SetIndexedPropertiesToExternalArrayData(array.get()->baseAddress(), arrayType, array.get()->length());
if (!srcArray.IsEmpty())
copyElements(args.Holder(), srcArray, 0);
v8::Persistent<v8::Object> wrapper = v8::Persistent<v8::Object>::New(args.Holder());
wrapper.MarkIndependent();
V8DOMWrapper::setJSWrapperForDOMObject(array.release(), wrapper);
return args.Holder();
}
template <class CPlusPlusArrayType, class JavaScriptWrapperArrayType>
v8::Handle<v8::Value> setWebGLArrayHelper(const v8::Arguments& args)
{
if (args.Length() < 1) {
V8Proxy::setDOMException(SYNTAX_ERR, args.GetIsolate());
return notHandledByInterceptor();
}
CPlusPlusArrayType* impl = JavaScriptWrapperArrayType::toNative(args.Holder());
if (JavaScriptWrapperArrayType::HasInstance(args[0])) {
CPlusPlusArrayType* src = JavaScriptWrapperArrayType::toNative(args[0]->ToObject());
uint32_t offset = 0;
if (args.Length() == 2)
offset = toUInt32(args[1]);
if (!impl->set(src, offset))
V8Proxy::setDOMException(INDEX_SIZE_ERR, args.GetIsolate());
return v8::Undefined();
}
if (args[0]->IsObject()) {
v8::Local<v8::Object> array = args[0]->ToObject();
uint32_t offset = 0;
if (args.Length() == 2)
offset = toUInt32(args[1]);
uint32_t length = toUInt32(array->Get(v8::String::New("length")));
if (offset > impl->length()
|| offset + length > impl->length()
|| offset + length < offset)
V8Proxy::setDOMException(INDEX_SIZE_ERR, args.GetIsolate());
else {
if (!fastSetInstalled(args.Holder())) {
installFastSet(args.Holder());
copyElements(args.Holder(), array, offset);
} else {
for (uint32_t i = 0; i < length; i++)
impl->set(offset + i, array->Get(i)->NumberValue());
}
}
return v8::Undefined();
}
V8Proxy::setDOMException(SYNTAX_ERR, args.GetIsolate());
return notHandledByInterceptor();
}
}
#endif // V8ArrayBufferViewCustom_h