/* * 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. */ #pragma once #if USING_IN_UNREAL_ENGINE #include "CoreMinimal.h" #include "UObject/Package.h" #include "UObject/Class.h" #else #include "JSClassRegister.h" #endif #include "NamespaceDef.h" PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS #pragma warning(push, 0) #include "v8.h" #pragma warning(pop) PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS #if !defined(MAPPER_ISOLATE_DATA_POS) #define MAPPER_ISOLATE_DATA_POS 0 #endif #ifndef PESAPI_PRIVATE_DATA_POS_IN_ISOLATE #define PESAPI_PRIVATE_DATA_POS_IN_ISOLATE (MAPPER_ISOLATE_DATA_POS + 1) #endif #define RELEASED_UOBJECT ((UObject*) 12) #define RELEASED_UOBJECT_MEMBER ((void*) 12) namespace PUERTS_NAMESPACE { template struct TOuterLinker { V8_INLINE static void Link(v8::Local Context, v8::Local Outer, v8::Local Inner) { } }; V8_INLINE void LinkOuterImpl(v8::Local Context, v8::Local Outer, v8::Local Inner) { #ifdef WITH_OUTER_LINK Inner.As()->Set(Context, 0, Outer); #endif } #if USING_IN_UNREAL_ENGINE FORCEINLINE UScriptStruct* GetScriptStructInCoreUObject(const TCHAR* Name) { static UPackage* CoreUObjectPkg = FindObjectChecked(nullptr, TEXT("/Script/CoreUObject")); return FindObjectChecked(CoreUObjectPkg, Name); } template struct TScriptStructTraits { }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return TBaseStructure::Get(); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return TBaseStructure::Get(); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return TBaseStructure::Get(); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return TBaseStructure::Get(); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return TBaseStructure::Get(); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return TBaseStructure::Get(); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return TBaseStructure::Get(); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return TBaseStructure::Get(); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return TBaseStructure::Get(); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return TBaseStructure::Get(); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return GetScriptStructInCoreUObject(TEXT("IntPoint")); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return GetScriptStructInCoreUObject(TEXT("IntVector")); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return GetScriptStructInCoreUObject(TEXT("Plane")); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return GetScriptStructInCoreUObject(TEXT("Matrix")); } }; template <> struct TScriptStructTraits { static UScriptStruct* Get() { return GetScriptStructInCoreUObject(TEXT("IntVector4")); } }; template using ToVoid = void; template struct HasStaticStructHelper : std::false_type { }; template struct HasStaticStructHelper> : std::true_type { }; template struct TScriptStructTraits::value>::type> { static UScriptStruct* Get() { return T::StaticStruct(); } }; template struct TOuterLinker::Get)>> { V8_INLINE static void Link(v8::Local Context, v8::Local Outer, v8::Local Inner) { LinkOuterImpl(Context, Outer, Inner); } }; #endif class JSENV_API DataTransfer { public: FORCEINLINE static void* MakeAddressWithHighPartOfTwo(void* Address1, void* Address2) { UPTRINT High = reinterpret_cast(Address1) & (((UPTRINT) -1) << (sizeof(UPTRINT) / 2)); //清除低位 UPTRINT Low = (reinterpret_cast(Address2) >> (sizeof(UPTRINT) / 2)) & ~(((UPTRINT) -1) << (sizeof(UPTRINT) / 2)); //右移,然后清除高位 return reinterpret_cast(High | Low); } FORCEINLINE static void SplitAddressToHighPartOfTwo(const void* Address, UPTRINT& High, UPTRINT& Low) { High = reinterpret_cast(Address) & (((UPTRINT) -1) << (sizeof(UPTRINT) / 2)); //清除低位 Low = reinterpret_cast(Address) << (sizeof(UPTRINT) / 2); } template FORCEINLINE static T* GetPointerFast(v8::Local Object, int Index) { int P1 = Index << 1; int P2 = P1 + 1; if (V8_LIKELY(Object->InternalFieldCount() > P2)) { return static_cast(MakeAddressWithHighPartOfTwo( Object->GetAlignedPointerFromInternalField(P1), Object->GetAlignedPointerFromInternalField(P2))); } return nullptr; } template FORCEINLINE static T* GetPointerFast(v8::Local Object) { if (V8_LIKELY(Object->InternalFieldCount() > 1)) { return static_cast(MakeAddressWithHighPartOfTwo( Object->GetAlignedPointerFromInternalField(0), Object->GetAlignedPointerFromInternalField(1))); } return nullptr; } //替代 Object->SetAlignedPointerInInternalField(Index, Ptr); FORCEINLINE static void SetPointer(v8::Isolate* Isolate, v8::Local Object, const void* Ptr, int Index) { // Object->SetInternalField(Index, v8::External::New(Isolate, Ptr)); // Object->SetAlignedPointerInInternalField(Index, Ptr); UPTRINT High; UPTRINT Low; SplitAddressToHighPartOfTwo(Ptr, High, Low); Object->SetAlignedPointerInInternalField(Index * 2, reinterpret_cast(High)); Object->SetAlignedPointerInInternalField(Index * 2 + 1, reinterpret_cast(Low)); } template FORCEINLINE static T* IsolateData(v8::Isolate* Isolate) { return static_cast(Isolate->GetData(MAPPER_ISOLATE_DATA_POS)); } FORCEINLINE static void* GetIsolatePrivateData(v8::Isolate* Isolate) { return Isolate->GetData(PESAPI_PRIVATE_DATA_POS_IN_ISOLATE); } FORCEINLINE static void SetIsolatePrivateData(v8::Isolate* Isolate, void* PrivateData) { Isolate->SetData(PESAPI_PRIVATE_DATA_POS_IN_ISOLATE, PrivateData); } static v8::Local FindOrAddCData( v8::Isolate* Isolate, v8::Local Context, const void* TypeId, const void* Ptr, bool PassByPointer); static bool IsInstanceOf(v8::Isolate* Isolate, const void* TypeId, v8::Local JsObject); static v8::Local UnRef(v8::Isolate* Isolate, const v8::Local& Value); static void UpdateRef(v8::Isolate* Isolate, v8::Local Outer, const v8::Local& Value); static std::weak_ptr GetJsEnvLifeCycleTracker(v8::Isolate* Isolate); #if USING_IN_UNREAL_ENGINE template static v8::Local FindOrAddObject(v8::Isolate* Isolate, v8::Local& Context, T* UEObject) { return FindOrAddObject(Isolate, Context, UEObject == nullptr ? T::StaticClass() : UEObject->GetClass(), UEObject); } static v8::Local FindOrAddObject( v8::Isolate* Isolate, v8::Local& Context, UClass* Class, UObject* UEObject); template static v8::Local FindOrAddStruct(v8::Isolate* Isolate, v8::Local Context, void* Ptr, bool PassByPointer) { return FindOrAddStruct(Isolate, Context, TScriptStructTraits::Get(), Ptr, PassByPointer); } static v8::Local FindOrAddStruct( v8::Isolate* Isolate, v8::Local Context, UScriptStruct* ScriptStruct, void* Ptr, bool PassByPointer); template static bool IsInstanceOf(v8::Isolate* Isolate, v8::Local JsObject) { return IsInstanceOf(Isolate, TScriptStructTraits::Get(), JsObject); } static bool IsInstanceOf(v8::Isolate* Isolate, UStruct* Struct, v8::Local JsObject); static FString ToFString(v8::Isolate* Isolate, v8::Local Value); static void ThrowException(v8::Isolate* Isolate, const char* Message); #endif template FORCEINLINE static void LinkOuter(v8::Local Context, v8::Local Outer, v8::Local Inner) { TOuterLinker::Link(Context, Outer, Inner); } FORCEINLINE static v8::Local NewArrayBuffer(v8::Local Context, void* Data, size_t DataLength) { #if defined(HAS_ARRAYBUFFER_NEW_WITHOUT_STL) return v8::ArrayBuffer_New_Without_Stl(Context->GetIsolate(), Data, DataLength); #else #if USING_IN_UNREAL_ENGINE return v8::ArrayBuffer::New(Context->GetIsolate(), Data, DataLength); #else auto Backing = v8::ArrayBuffer::NewBackingStore(Data, DataLength, v8::BackingStore::EmptyDeleter, nullptr); return v8::ArrayBuffer::New(Context->GetIsolate(), std::move(Backing)); #endif #endif } FORCEINLINE static void* GetArrayBufferData(v8::Local InArrayBuffer) { size_t DataLength; return GetArrayBufferData(InArrayBuffer, DataLength); } FORCEINLINE static void* GetArrayBufferData(v8::Local InArrayBuffer, size_t& DataLength) { #if defined(HAS_ARRAYBUFFER_NEW_WITHOUT_STL) return v8::ArrayBuffer_Get_Data(InArrayBuffer, DataLength); #else #if USING_IN_UNREAL_ENGINE DataLength = InArrayBuffer->GetContents().ByteLength(); return InArrayBuffer->GetContents().Data(); #else auto BS = InArrayBuffer->GetBackingStore(); DataLength = BS->ByteLength(); return BS->Data(); #endif #endif } }; } // namespace PUERTS_NAMESPACE