#include "UnmanagedType.h" #include "NativeScriptException.h" #include "Caches.h" #include "Helpers.h" #include "Interop.h" using namespace v8; namespace tns { Local UnmanagedType::Create(Local context, UnmanagedTypeWrapper* wrapper) { Isolate* isolate = context->GetIsolate(); auto cache = Caches::Get(isolate); if (cache->UnmanagedTypeCtorFunc.get() == nullptr) { Local ctorFuncTemplate = FunctionTemplate::New(isolate, ConstructorCallback); ctorFuncTemplate->SetClassName(tns::ToV8String(isolate, "Unmanaged")); Local proto = ctorFuncTemplate->PrototypeTemplate(); Local takeUnretainedValueFuncTemplate = FunctionTemplate::New(isolate, UnmanagedType::TakeUnretainedValueCallback); Local takeRetainedValueFuncTemplate = FunctionTemplate::New(isolate, UnmanagedType::TakeRetainedValueCallback); proto->Set(tns::ToV8String(isolate, "takeUnretainedValue"), takeUnretainedValueFuncTemplate); proto->Set(tns::ToV8String(isolate, "takeRetainedValue"), takeRetainedValueFuncTemplate); Local ctorFunc; bool success = ctorFuncTemplate->GetFunction(context).ToLocal(&ctorFunc); tns::Assert(success, isolate); cache->UnmanagedTypeCtorFunc = std::make_unique>(isolate, ctorFunc); } Local ext = External::New(isolate, wrapper); Local ctorFunc = cache->UnmanagedTypeCtorFunc->Get(isolate); Local result; Local args[] = { ext }; bool success = ctorFunc->NewInstance(context, 1, args).ToLocal(&result); tns::Assert(success, isolate); return result; } void UnmanagedType::ConstructorCallback(const FunctionCallbackInfo& info) { Local ext = info[0].As(); UnmanagedTypeWrapper* wrapper = static_cast(ext->Value()); tns::SetValue(info.GetIsolate(), info.This(), wrapper); } void UnmanagedType::TakeUnretainedValueCallback(const FunctionCallbackInfo& info) { try { info.GetReturnValue().Set(UnmanagedType::TakeValue(info, false)); } catch (NativeScriptException& ex) { ex.ReThrowToV8(info.GetIsolate()); } } void UnmanagedType::TakeRetainedValueCallback(const FunctionCallbackInfo& info) { try { info.GetReturnValue().Set(UnmanagedType::TakeValue(info, true)); } catch (NativeScriptException& ex) { ex.ReThrowToV8(info.GetIsolate()); } } Local UnmanagedType::TakeValue(const FunctionCallbackInfo& info, bool retained) { Isolate* isolate = info.GetIsolate(); Local context = isolate->GetCurrentContext(); BaseDataWrapper* baseWrapper = tns::GetValue(isolate, info.This()); UnmanagedTypeWrapper* wrapper = static_cast(baseWrapper); if (wrapper->ValueTaken()) { throw NativeScriptException("Unmanaged value has already been consumed."); } uint8_t* data = wrapper->Data(); const TypeEncoding* typeEncoding = wrapper->TypeEncoding(); BaseCall call((uint8_t*)&data); Local result = Interop::GetResult(context, typeEncoding, &call, false); if (retained) { id value = static_cast((void*)data); [value release]; } return result; } }