#include "ExtVector.h" #include "ObjectManager.h" #include "FFICall.h" #include "Caches.h" #include "Interop.h" #include "Helpers.h" using namespace v8; namespace tns { Local ExtVector::NewInstance(Isolate* isolate, void* data, ffi_type* ffiType, const TypeEncoding* innerTypeEncoding, const TypeEncoding* typeEncoding) { Local ctorFuncTemplate = FunctionTemplate::New(isolate); ctorFuncTemplate->InstanceTemplate()->SetInternalFieldCount(1); ctorFuncTemplate->InstanceTemplate()->SetHandler(IndexedPropertyHandlerConfiguration(IndexedPropertyGetCallback, IndexedPropertySetCallback)); ctorFuncTemplate->SetClassName(tns::ToV8String(isolate, "ExtVector")); ExtVector::RegisterToStringMethod(isolate, ctorFuncTemplate->PrototypeTemplate()); Local context = isolate->GetCurrentContext(); Local result; bool success = ctorFuncTemplate->InstanceTemplate()->NewInstance(context).ToLocal(&result); tns::Assert(success, isolate); // TODO: Validate that the inner type is supported (float, double) ExtVectorWrapper* wrapper = MakeGarbageCollected(isolate, data, ffiType, innerTypeEncoding, typeEncoding); tns::SetValue(isolate, result.As(), wrapper); return result; } void ExtVector::IndexedPropertyGetCallback(uint32_t index, const PropertyCallbackInfo& info) { Isolate* isolate = info.GetIsolate(); Local context = isolate->GetCurrentContext(); BaseDataWrapper* wrapper = tns::GetValue(isolate, info.This()); tns::Assert(wrapper != nullptr && wrapper->Type() == WrapperType::ExtVector, isolate); ExtVectorWrapper* extVectorWrapper = static_cast(wrapper); const TypeEncoding* innerTypeEncoding = extVectorWrapper->InnerTypeEncoding(); ffi_type* innerFFIType = FFICall::GetArgumentType(innerTypeEncoding); size_t offset = index * innerFFIType->size; FFICall::DisposeFFIType(innerFFIType, innerTypeEncoding); ffi_type* ffiType = extVectorWrapper->FFIType(); if (offset >= ffiType->size) { // Trying to access an element outside of the vector size info.GetReturnValue().SetUndefined(); return; } void* data = extVectorWrapper->Data(); BaseCall call((uint8_t*)data, offset); Local result = Interop::GetPrimitiveReturnType(context, innerTypeEncoding->type, &call); info.GetReturnValue().Set(result); } void ExtVector::IndexedPropertySetCallback(uint32_t index, Local value, const PropertyCallbackInfo& info) { Isolate* isolate = info.GetIsolate(); Local context = isolate->GetCurrentContext(); BaseDataWrapper* wrapper = tns::GetValue(isolate, info.This()); tns::Assert(wrapper != nullptr && wrapper->Type() == WrapperType::ExtVector, isolate); ExtVectorWrapper* extVectorWrapper = static_cast(wrapper); const TypeEncoding* innerTypeEncoding = extVectorWrapper->InnerTypeEncoding(); ffi_type* innerFFIType = FFICall::GetArgumentType(innerTypeEncoding); size_t offset = index * innerFFIType->size; FFICall::DisposeFFIType(innerFFIType, innerTypeEncoding); ffi_type* ffiType = extVectorWrapper->FFIType(); if (offset >= ffiType->size) { // Trying to access an element outside of the vector size return; } void* data = extVectorWrapper->Data(); void* dest = (uint8_t*)data + offset; Interop::WriteValue(context, innerTypeEncoding, dest, value); } void ExtVector::RegisterToStringMethod(Isolate* isolate, Local prototypeTemplate) { Local funcTemplate = FunctionTemplate::New(isolate, [](const FunctionCallbackInfo& info) { Isolate* isolate = info.GetIsolate(); ExtVectorWrapper* wrapper = ExtractWrapper(info.This()); void* value = wrapper->Data(); char buffer[100]; snprintf(buffer, 100, "", value); Local result = tns::ToV8String(isolate, buffer); info.GetReturnValue().Set(result); }); prototypeTemplate->Set(tns::ToV8String(isolate, "toString"), funcTemplate); } }