Files
AncientCivil/Plugins/Puerts/Source/JsEnv/Private/ContainerWrapper.cpp
T
2025-02-10 00:44:11 +08:00

851 lines
33 KiB
C++

/*
* Tencent is pleased to support the open source community by making Puerts available.
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may
* be subject to their corresponding license terms. This file is subject to the terms and conditions defined in file 'LICENSE',
* which is part of this source code package.
*/
#include "ContainerWrapper.h"
#include "PropertyTranslator.h"
namespace PUERTS_NAMESPACE
{
v8::Local<v8::FunctionTemplate> FScriptArrayWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
{
v8::Isolate::Scope Isolatescope(Isolate);
auto Result = v8::FunctionTemplate::New(Isolate, New);
Result->InstanceTemplate()->SetInternalFieldCount(4); // 0 Ptr, 1 Property
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Num"), v8::FunctionTemplate::New(Isolate, Num));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Add"), v8::FunctionTemplate::New(Isolate, Add));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Get"), v8::FunctionTemplate::New(Isolate, Get));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "GetRef"), v8::FunctionTemplate::New(Isolate, GetRef));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Set"), v8::FunctionTemplate::New(Isolate, Set));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Contains"), v8::FunctionTemplate::New(Isolate, Contains));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "FindIndex"), v8::FunctionTemplate::New(Isolate, FindIndex));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "RemoveAt"), v8::FunctionTemplate::New(Isolate, RemoveAt));
Result->PrototypeTemplate()->Set(
FV8Utils::InternalString(Isolate, "IsValidIndex"), v8::FunctionTemplate::New(Isolate, IsValidIndex));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Empty"), v8::FunctionTemplate::New(Isolate, Empty));
return Result;
}
void FScriptArrayWrapper::Add(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
if (Info.Length() > 0)
{
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
int32 Index = AddUninitialized(Self, GetSizeWithAlignment(Inner->Property), Info.Length());
for (int i = 0; i < Info.Length(); ++i)
{
uint8* DataPtr = GetData(Self, GetSizeWithAlignment(Inner->Property), Index + i);
Inner->Property->InitializeValue(DataPtr); //使用之前必须得初始化,即使是设置也要
Inner->JsToUE(Isolate, Context, Info[i], DataPtr, false);
}
Info.GetReturnValue().Set(Index);
}
}
void FScriptArrayWrapper::InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
int Index = Info[0]->Int32Value(Context).ToChecked();
if (Index < 0 || Index >= Self->Num())
{
FV8Utils::ThrowException(Isolate, TEXT("invalid index"));
return;
}
uint8* DataPtr = GetData(Self, GetSizeWithAlignment(Inner->Property), Index);
auto Ret = Inner->UEToJs(Isolate, Context, DataPtr, PassByPointer);
if (Inner->NeedLinkOuter && PassByPointer)
{
LinkOuterImpl(Context, Info.Holder(), Ret);
}
Info.GetReturnValue().Set(Ret);
}
void FScriptArrayWrapper::Get(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
InternalGet(Info, false);
}
void FScriptArrayWrapper::GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
InternalGet(Info, true);
}
void FScriptArrayWrapper::Set(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(2);
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
int Index = Info[0]->Int32Value(Context).ToChecked();
if (Index < 0 || Index >= Self->Num())
{
FV8Utils::ThrowException(Isolate, TEXT("invalid index"));
return;
}
uint8* DataPtr = GetData(Self, GetSizeWithAlignment(Inner->Property), Index);
Inner->Property->InitializeValue(DataPtr);
Inner->JsToUE(Isolate, Context, Info[1], DataPtr, false);
}
void FScriptArrayWrapper::Contains(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
CHECK_V8_ARGS_LEN(1);
bool Result = FindIndexInner(Info) != INDEX_NONE;
Info.GetReturnValue().Set(Result);
}
void FScriptArrayWrapper::FindIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
CHECK_V8_ARGS_LEN(1);
int32 Result = FindIndexInner(Info);
Info.GetReturnValue().Set(Result);
}
void FScriptArrayWrapper::RemoveAt(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
int32 Index = Info[0]->Int32Value(Context).ToChecked();
if (Index < 0 || Index >= Self->Num())
{
FV8Utils::ThrowException(Isolate, TEXT("invalid index"));
return;
}
else
{
FScriptArrayEx::Destruct(Self, Inner->Property, Index, 1);
#if ENGINE_MAJOR_VERSION > 4
Self->Remove(Index, 1, GetSizeWithAlignment(Inner->Property), __STDCPP_DEFAULT_NEW_ALIGNMENT__);
#else
Self->Remove(Index, 1, GetSizeWithAlignment(Inner->Property));
#endif
}
}
void FScriptArrayWrapper::IsValidIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
int32 Index = Info[0]->Int32Value(Context).ToChecked();
Info.GetReturnValue().Set(Self->IsValidIndex(Index));
}
void FScriptArrayWrapper::Empty(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
FScriptArrayEx::Empty(Self, Inner->Property);
}
FORCEINLINE int32 FScriptArrayWrapper::AddUninitialized(FScriptArray* ScriptArray, int32 ElementSize, int32 Count)
{
#if ENGINE_MAJOR_VERSION > 4
return ScriptArray->Add(Count, ElementSize, __STDCPP_DEFAULT_NEW_ALIGNMENT__);
#else
return ScriptArray->Add(Count, ElementSize);
#endif
}
FORCEINLINE uint8* FScriptArrayWrapper::GetData(FScriptArray* ScriptArray, int32 ElementSize, int32 Index)
{
return reinterpret_cast<uint8*>(ScriptArray->GetData()) + Index * ElementSize;
}
FORCEINLINE void FScriptArrayWrapper::Construct(FScriptArray* ScriptArray, FPropertyTranslator* Inner, int32 Index, int32 Count)
{
int32 ElementSize = GetSizeWithAlignment(Inner->Property);
uint8* Dest = GetData(ScriptArray, ElementSize, Index);
for (int32 i = 0; i < Count; ++i)
{
Inner->Property->InitializeValue(Dest);
Dest += ElementSize;
}
}
int32 FScriptArrayWrapper::FindIndexInner(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
auto Self = FV8Utils::GetPointerFast<FScriptArray>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return INDEX_NONE;
}
auto Property = Inner->Property;
void* Dest = FMemory_Alloca(GetSizeWithAlignment(Property));
Property->InitializeValue(Dest);
Inner->JsToUE(Isolate, Context, Info[0], Dest, false);
const int32 Num = Self->Num();
int32 Result = INDEX_NONE;
for (int32 i = 0; i < Num; ++i)
{
uint8* Src = GetData(Self, GetSizeWithAlignment(Property), i);
if (Property->Identical(Src, Dest))
{
Result = i;
break;
}
}
Property->DestroyValue(Dest);
return Result;
}
//---------------------------------------Set-----------------------------------------------
v8::Local<v8::FunctionTemplate> FScriptSetWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
{
v8::Isolate::Scope Isolatescope(Isolate);
auto Result = v8::FunctionTemplate::New(Isolate, New);
Result->InstanceTemplate()->SetInternalFieldCount(4); // 0 Ptr, 1 Property
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Num"), v8::FunctionTemplate::New(Isolate, Num));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Add"), v8::FunctionTemplate::New(Isolate, Add));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Get"), v8::FunctionTemplate::New(Isolate, Get));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "GetRef"), v8::FunctionTemplate::New(Isolate, GetRef));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Contains"), v8::FunctionTemplate::New(Isolate, Contains));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "FindIndex"), v8::FunctionTemplate::New(Isolate, FindIndex));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "RemoveAt"), v8::FunctionTemplate::New(Isolate, RemoveAt));
Result->PrototypeTemplate()->Set(
FV8Utils::InternalString(Isolate, "GetMaxIndex"), v8::FunctionTemplate::New(Isolate, GetMaxIndex));
Result->PrototypeTemplate()->Set(
FV8Utils::InternalString(Isolate, "IsValidIndex"), v8::FunctionTemplate::New(Isolate, IsValidIndex));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Empty"), v8::FunctionTemplate::New(Isolate, Empty));
return Result;
}
void FScriptSetWrapper::Add(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
auto Property = Inner->Property;
void* DataPtr = FMemory_Alloca(GetSizeWithAlignment(Property));
Property->InitializeValue(DataPtr);
Inner->JsToUE(Isolate, Context, Info[0], DataPtr, false);
auto ScriptLayout = FScriptSet::GetScriptLayout(Property->GetSize(), Property->GetMinAlignment());
Self->Add(
DataPtr, ScriptLayout, [Property](const void* Element) { return Property->GetValueTypeHash(Element); },
[Property](const void* A, const void* B) { return Property->Identical(A, B); },
[Property, DataPtr](void* Element)
{
Property->InitializeValue(Element);
Property->CopySingleValue(Element, DataPtr);
},
[Property](void* Element) { Property->DestroyValue(Element); });
Property->DestroyValue(DataPtr);
}
void FScriptSetWrapper::InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
auto Property = Inner->Property;
int32 Index = Info[0]->Int32Value(Context).ToChecked();
if (Self->IsValidIndex(Index) == false)
{
FV8Utils::ThrowException(Isolate, "invalid index argument");
}
else
{
auto ScriptLayout = FScriptSet::GetScriptLayout(Property->GetSize(), Property->GetMinAlignment());
void* Data = Self->GetData(Index, ScriptLayout);
auto Ret = Inner->UEToJs(Isolate, Context, Data, PassByPointer);
if (Inner->NeedLinkOuter && PassByPointer)
{
LinkOuterImpl(Context, Info.Holder(), Ret);
}
Info.GetReturnValue().Set(Ret);
}
}
void FScriptSetWrapper::Get(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
InternalGet(Info, false);
}
void FScriptSetWrapper::GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
InternalGet(Info, true);
}
void FScriptSetWrapper::Contains(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
CHECK_V8_ARGS_LEN(1);
bool Result = FindIndexInner(Info) != INDEX_NONE;
Info.GetReturnValue().Set(Result);
}
void FScriptSetWrapper::FindIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
CHECK_V8_ARGS_LEN(1);
int32 Result = FindIndexInner(Info);
Info.GetReturnValue().Set(Result);
}
void FScriptSetWrapper::RemoveAt(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
auto Property = Inner->Property;
int32 Index = Info[0]->Int32Value(Context).ToChecked();
if (Self->IsValidIndex(Index) == false)
{
FV8Utils::ThrowException(Isolate, "invalid index argument");
}
else
{
auto ScriptLayout = FScriptSet::GetScriptLayout(Property->GetSize(), Property->GetMinAlignment());
void* Data = Self->GetData(Index, ScriptLayout);
FScriptSetEx::Destruct(Self, Property, Index, 1);
Self->RemoveAt(Index, ScriptLayout);
}
}
void FScriptSetWrapper::GetMaxIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
uint32 Result = Self->GetMaxIndex();
Info.GetReturnValue().Set(Result);
}
void FScriptSetWrapper::IsValidIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
int32 Index = Info[0]->Int32Value(Context).ToChecked();
uint32 Result = Self->IsValidIndex(Index);
Info.GetReturnValue().Set(Result);
}
void FScriptSetWrapper::Empty(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
FScriptSetEx::Empty(Self, Inner->Property);
}
int32 FScriptSetWrapper::FindIndexInner(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
auto Self = FV8Utils::GetPointerFast<FScriptSet>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return INDEX_NONE;
}
auto Property = Inner->Property;
void* DataPtr = FMemory_Alloca(GetSizeWithAlignment(Property));
Property->InitializeValue(DataPtr);
Inner->JsToUE(Isolate, Context, Info[0], DataPtr, false);
auto ScriptLayout = FScriptSet::GetScriptLayout(Property->GetSize(), Property->GetMinAlignment());
int32 Result = Self->FindIndex(
DataPtr, ScriptLayout, [Property](const void* Element) { return Property->GetValueTypeHash(Element); },
[Property](const void* A, const void* B) { return Property->Identical(A, B); });
Property->DestroyValue(DataPtr);
return Result;
}
//---------------------------------------Map-----------------------------------------------
v8::Local<v8::FunctionTemplate> FScriptMapWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
{
v8::Isolate::Scope Isolatescope(Isolate);
auto Result = v8::FunctionTemplate::New(Isolate, New);
Result->InstanceTemplate()->SetInternalFieldCount(6); // 0 Ptr, 1-2 Property
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Num"), v8::FunctionTemplate::New(Isolate, Num));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Add"), v8::FunctionTemplate::New(Isolate, Add));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Get"), v8::FunctionTemplate::New(Isolate, Get));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "GetRef"), v8::FunctionTemplate::New(Isolate, GetRef));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Set"), v8::FunctionTemplate::New(Isolate, Set));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Remove"), v8::FunctionTemplate::New(Isolate, Remove));
Result->PrototypeTemplate()->Set(
FV8Utils::InternalString(Isolate, "GetMaxIndex"), v8::FunctionTemplate::New(Isolate, GetMaxIndex));
Result->PrototypeTemplate()->Set(
FV8Utils::InternalString(Isolate, "IsValidIndex"), v8::FunctionTemplate::New(Isolate, IsValidIndex));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "GetKey"), v8::FunctionTemplate::New(Isolate, GetKey));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Empty"), v8::FunctionTemplate::New(Isolate, Empty));
return Result;
}
void FScriptMapWrapper::Add(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(2);
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
auto KeyPropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
auto KeyProperty = KeyPropertyTranslator->Property;
auto ValuePropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 2);
auto ValueProperty = ValuePropertyTranslator->Property;
if (!KeyPropertyTranslator->IsPropertyValid() || !ValuePropertyTranslator->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "key/value info is invalid!");
return;
}
void* KeyPtr = FMemory_Alloca(GetSizeWithAlignment(KeyProperty));
KeyProperty->InitializeValue(KeyPtr);
void* ValuePtr = FMemory_Alloca(GetSizeWithAlignment(ValueProperty));
ValueProperty->InitializeValue(ValuePtr);
KeyPropertyTranslator->JsToUE(Isolate, Context, Info[0], KeyPtr, false);
ValuePropertyTranslator->JsToUE(Isolate, Context, Info[1], ValuePtr, false);
auto ScriptLayout = FScriptMap::GetScriptLayout(
KeyProperty->GetSize(), KeyProperty->GetMinAlignment(), ValueProperty->GetSize(), ValueProperty->GetMinAlignment());
Self->Add(
KeyPtr, ValuePtr, ScriptLayout, [KeyProperty](const void* ElementKey) { return KeyProperty->GetValueTypeHash(ElementKey); },
[KeyProperty](const void* A, const void* B) { return KeyProperty->Identical(A, B); },
[KeyProperty, KeyPtr](void* NewElementKey)
{
KeyProperty->InitializeValue(NewElementKey);
KeyProperty->CopySingleValue(NewElementKey, KeyPtr);
},
[ValueProperty, ValuePtr](void* NewElementValue)
{
ValueProperty->InitializeValue(NewElementValue);
ValueProperty->CopySingleValue(NewElementValue, ValuePtr);
},
[ValueProperty, ValuePtr](void* ExistingElementValue) { ValueProperty->CopySingleValue(ExistingElementValue, ValuePtr); },
[KeyProperty](void* ElementKey) { KeyProperty->DestroyValue(ElementKey); },
[ValueProperty](void* ElementValue) { ValueProperty->DestroyValue(ElementValue); });
KeyProperty->DestroyValue(KeyPtr);
ValueProperty->DestroyValue(ValuePtr);
}
void FScriptMapWrapper::InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
auto KeyPropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
auto KeyProperty = KeyPropertyTranslator->Property;
auto ValuePropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 2);
auto ValueProperty = ValuePropertyTranslator->Property;
if (!KeyPropertyTranslator->IsPropertyValid() || !ValuePropertyTranslator->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "key/value info is invalid!");
return;
}
void* KeyPtr = FMemory_Alloca(GetSizeWithAlignment(KeyProperty));
KeyProperty->InitializeValue(KeyPtr);
KeyPropertyTranslator->JsToUE(Isolate, Context, Info[0], KeyPtr, false);
auto ScriptLayout = FScriptMap::GetScriptLayout(
KeyProperty->GetSize(), KeyProperty->GetMinAlignment(), ValueProperty->GetSize(), ValueProperty->GetMinAlignment());
void* ValuePtr = Self->FindValue(
KeyPtr, ScriptLayout, [KeyProperty](const void* ElementKey) { return KeyProperty->GetValueTypeHash(ElementKey); },
[KeyProperty](const void* A, const void* B) { return KeyProperty->Identical(A, B); });
if (ValuePtr)
{
auto Ret = ValuePropertyTranslator->UEToJs(Isolate, Context, ValuePtr, PassByPointer);
if (ValuePropertyTranslator->NeedLinkOuter && PassByPointer)
{
LinkOuterImpl(Context, Info.Holder(), Ret);
}
Info.GetReturnValue().Set(Ret);
}
KeyProperty->DestroyValue(KeyPtr);
}
void FScriptMapWrapper::Get(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
InternalGet(Info, false);
}
void FScriptMapWrapper::GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
InternalGet(Info, true);
}
void FScriptMapWrapper::Set(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
Add(Info);
}
void FScriptMapWrapper::Remove(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
auto KeyPropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
auto KeyProperty = KeyPropertyTranslator->Property;
auto ValuePropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 2);
auto ValueProperty = ValuePropertyTranslator->Property;
if (!KeyPropertyTranslator->IsPropertyValid() || !ValuePropertyTranslator->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "key/value info is invalid!");
return;
}
void* KeyPtr = FMemory_Alloca(GetSizeWithAlignment(KeyProperty));
KeyProperty->InitializeValue(KeyPtr);
KeyPropertyTranslator->JsToUE(Isolate, Context, Info[0], KeyPtr, false);
auto ScriptLayout = GetScriptLayout(KeyProperty, ValueProperty);
int32 Index = Self->FindPairIndex(
KeyPtr, ScriptLayout, [KeyProperty](const void* Key) { return KeyProperty->GetValueTypeHash(Key); },
[KeyProperty](const void* A, const void* B) { return KeyProperty->Identical(A, B); });
if (Index == INDEX_NONE)
{
FV8Utils::ThrowException(Isolate, TEXT("invalid key argument"));
}
else
{
FScriptMapEx::Destruct(Self, KeyProperty, ValueProperty, Index, 1);
Self->RemoveAt(Index, ScriptLayout);
}
KeyProperty->DestroyValue(KeyPtr);
}
void FScriptMapWrapper::GetMaxIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
int32 Result = Self->GetMaxIndex();
Info.GetReturnValue().Set(Result);
}
void FScriptMapWrapper::IsValidIndex(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
int32 Index = Info[0]->Int32Value(Context).ToChecked();
Info.GetReturnValue().Set(Self->IsValidIndex(Index));
}
void FScriptMapWrapper::GetKey(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
CHECK_V8_ARGS_LEN(1);
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
int32 Index = Info[0]->Int32Value(Context).ToChecked();
if (Self->IsValidIndex(Index) == false)
{
FV8Utils::ThrowException(Isolate, TEXT("the argument is an invalid index"));
Info.GetReturnValue().Set(v8::Undefined(Isolate));
}
else
{
auto KeyPropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
auto KeyProperty = KeyPropertyTranslator->Property;
auto ValuePropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 2);
auto ValueProperty = ValuePropertyTranslator->Property;
if (!KeyPropertyTranslator->IsPropertyValid() || !ValuePropertyTranslator->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "key/value info is invalid!");
return;
}
auto ScriptLayout = GetScriptLayout(KeyProperty, ValueProperty);
uint8* Data = reinterpret_cast<uint8*>(Self->GetData(Index, ScriptLayout));
void* KeyPtr = Data + GetKeyOffset(ScriptLayout);
Info.GetReturnValue().Set(KeyPropertyTranslator->UEToJs(Isolate, Context, KeyPtr, false));
}
}
void FScriptMapWrapper::Empty(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
auto Self = FV8Utils::GetPointerFast<FScriptMap>(Info.Holder(), 0);
auto KeyPropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
auto KeyProperty = KeyPropertyTranslator->Property;
auto ValuePropertyTranslator = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 2);
auto ValueProperty = ValuePropertyTranslator->Property;
if (!KeyPropertyTranslator->IsPropertyValid() || !ValuePropertyTranslator->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "key/value info is invalid!");
return;
}
FScriptMapEx::Empty(Self, KeyProperty, ValueProperty);
}
FScriptMapLayout FScriptMapWrapper::GetScriptLayout(const PropertyMacro* KeyProperty, const PropertyMacro* ValueProperty)
{
return FScriptMap::GetScriptLayout(
KeyProperty->GetSize(), KeyProperty->GetMinAlignment(), ValueProperty->GetSize(), ValueProperty->GetMinAlignment());
}
//---------------------------------------Fix Size Array-----------------------------------------------
v8::Local<v8::FunctionTemplate> FFixSizeArrayWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
{
v8::Isolate::Scope Isolatescope(Isolate);
auto Result = v8::FunctionTemplate::New(Isolate, New);
Result->InstanceTemplate()->SetInternalFieldCount(4); // 0 Ptr, 1 Property
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Num"), v8::FunctionTemplate::New(Isolate, Num));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Get"), v8::FunctionTemplate::New(Isolate, Get));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "GetRef"), v8::FunctionTemplate::New(Isolate, GetRef));
Result->PrototypeTemplate()->Set(FV8Utils::InternalString(Isolate, "Set"), v8::FunctionTemplate::New(Isolate, Set));
// Result->PrototypeTemplate()->SetIndexedPropertyHandler(Getter, Setter);
return Result;
}
void FFixSizeArrayWrapper::Num(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
Info.GetReturnValue().Set(Inner->Property->ArrayDim);
}
void FFixSizeArrayWrapper::InternalGet(const v8::FunctionCallbackInfo<v8::Value>& Info, bool PassByPointer)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
auto Self = FV8Utils::GetPointerFast<uint8>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
auto Property = Inner->Property;
int32 Index = -1;
if (Info[0]->IsInt32())
{
Index = Info[0]->Int32Value(Context).ToChecked();
}
if (Index < 0 || Index >= Property->ArrayDim)
{
FV8Utils::ThrowException(Isolate, "invalid index");
return;
}
auto Ptr = Self + Property->ElementSize * Index;
auto Ret = Inner->UEToJs(Isolate, Context, Ptr, PassByPointer);
if (Inner->NeedLinkOuter && PassByPointer)
{
LinkOuterImpl(Context, Info.Holder(), Ret);
}
Info.GetReturnValue().Set(Ret);
}
void FFixSizeArrayWrapper::Get(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
InternalGet(Info, false);
}
void FFixSizeArrayWrapper::GetRef(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
InternalGet(Info, true);
}
void FFixSizeArrayWrapper::Set(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
auto Self = FV8Utils::GetPointerFast<uint8>(Info.Holder(), 0);
auto Inner = FV8Utils::GetPointerFast<FPropertyTranslator>(Info.Holder(), 1);
if (!Inner->IsPropertyValid())
{
FV8Utils::ThrowException(Isolate, "item info is invalid!");
return;
}
auto Property = Inner->Property;
int32 Index = -1;
if (Info[0]->IsInt32())
{
Index = Info[0]->Int32Value(Context).ToChecked();
}
if (Index < 0 || Index >= Property->ArrayDim)
{
FV8Utils::ThrowException(Isolate, "invalid index");
return;
}
auto Ptr = Self + Property->ElementSize * Index;
Inner->JsToUE(Isolate, Context, Info[1], Ptr, true);
}
} // namespace PUERTS_NAMESPACE