From d5b8128a122e2b9735d8a9b787fdb5b191f35f4c Mon Sep 17 00:00:00 2001 From: Tangxinwei Date: Tue, 20 Feb 2024 15:25:03 +0800 Subject: [PATCH] =?UTF-8?q?[unreal]=E5=A2=9E=E5=8A=A0=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E5=AE=8F=EF=BC=8C=E5=85=81=E8=AE=B8ts=E4=B8=8D=E6=8C=81?= =?UTF-8?q?=E6=9C=89ueobject=20(#1660)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 增加宏,允许ts不主动持有ueobject * clang-format * rename * rename --- .../Content/JavaScript/puerts/uelazyload.js | 3 + unreal/Puerts/Source/JsEnv/JsEnv.Build.cs | 10 +++ .../Puerts/Source/JsEnv/Private/JsEnvImpl.cpp | 70 +++++++++++++++---- .../Puerts/Source/JsEnv/Private/JsEnvImpl.h | 4 ++ .../Source/JsEnv/Private/StructWrapper.h | 4 ++ unreal/Puerts/Typing/puerts/index.d.ts | 2 + unreal/Puerts/Typing/ue/puerts.d.ts | 2 +- 7 files changed, 82 insertions(+), 13 deletions(-) diff --git a/unreal/Puerts/Content/JavaScript/puerts/uelazyload.js b/unreal/Puerts/Content/JavaScript/puerts/uelazyload.js index af4b785729..e3c8df0ea9 100644 --- a/unreal/Puerts/Content/JavaScript/puerts/uelazyload.js +++ b/unreal/Puerts/Content/JavaScript/puerts/uelazyload.js @@ -122,6 +122,9 @@ var global = global || (function () { return this; }()); let rawmakeclass = global.__tgjsMakeUClass global.__tgjsMakeUClass = undefined; + + puerts.setJsTakeRef = global.__tgjsSetJsTakeRef + global.__tgjsSetJsTakeRef = undefined function defaultUeConstructor(){}; diff --git a/unreal/Puerts/Source/JsEnv/JsEnv.Build.cs b/unreal/Puerts/Source/JsEnv/JsEnv.Build.cs index 57f430aac6..b34c5d8b9c 100644 --- a/unreal/Puerts/Source/JsEnv/JsEnv.Build.cs +++ b/unreal/Puerts/Source/JsEnv/JsEnv.Build.cs @@ -87,6 +87,16 @@ public JsEnv(ReadOnlyTargetRules Target) : base(Target) PublicDefinitions.Add("PUERTS_FORCE_CPP_UFUNCTION=0"); } + bool bKeepUObjectReference = true; + if(bKeepUObjectReference) + { + PublicDefinitions.Add("PUERTS_KEEP_UOBJECT_REFERENCE=1"); + } + else + { + PublicDefinitions.Add("PUERTS_KEEP_UOBJECT_REFERENCE=0"); + } + bool UseWasm = false; if (UseWasm) { diff --git a/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp b/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp index 86a8e880ec..194ab9687a 100644 --- a/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp +++ b/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp @@ -498,6 +498,8 @@ FJsEnvImpl::FJsEnvImpl(std::shared_ptr InModuleLoader, std::sha MethodBindingHelper<&FJsEnvImpl::NewObjectByClass>::Bind(Isolate, Context, Global, "__tgjsNewObject", This); + MethodBindingHelper<&FJsEnvImpl::SetJsTakeRefInTs>::Bind(Isolate, Context, Global, "__tgjsSetJsTakeRef", This); + MethodBindingHelper<&FJsEnvImpl::NewStructByScriptStruct>::Bind(Isolate, Context, Global, "__tgjsNewStruct", This); #if !defined(ENGINE_INDEPENDENT_JSENV) @@ -1032,7 +1034,7 @@ void FJsEnvImpl::NewObjectByClass(const v8::FunctionCallbackInfo& Inf if (Class) { - if (Info.Length() > 1) + if (Info.Length() > 1 && !Info[1]->IsNullOrUndefined()) { Outer = FV8Utils::GetUObject(Context, Info[1]); if (FV8Utils::IsReleasedPtr(Outer)) @@ -1041,17 +1043,37 @@ void FJsEnvImpl::NewObjectByClass(const v8::FunctionCallbackInfo& Inf return; } } - if (Info.Length() > 2) + if (Info.Length() > 2 && !Info[2]->IsNullOrUndefined()) { Name = FName(*FV8Utils::ToFString(Isolate, Info[2])); } - if (Info.Length() > 3) + if (Info.Length() > 3 && !Info[3]->IsNullOrUndefined()) { ObjectFlags = (EObjectFlags) (Info[3]->Int32Value(Context).ToChecked()); } UObject* Object = NewObject(Outer, Class, Name, ObjectFlags); auto Result = FV8Utils::IsolateData(Isolate)->FindOrAdd(Isolate, Context, Object->GetClass(), Object); + bool NeedJsTakeRef = true; + if (Info.Length() > 4 && !Info[4]->IsNullOrUndefined()) + { + if (Info[4]->BooleanValue(Isolate)) + { + } + else + { + NeedJsTakeRef = false; + } + } +#if PUERTS_KEEP_UOBJECT_REFERENCE +#else + if (NeedJsTakeRef) + { + bool Existed; + auto TemplateInfoPtr = GetTemplateInfoOfType(Class, Existed); + SetJsTakeRef(Object, static_cast(TemplateInfoPtr->StructWrapper.get())); + } +#endif Info.GetReturnValue().Set(Result); } else @@ -1683,22 +1705,33 @@ bool FJsEnvImpl::IsTypeScriptGeneratedClass(UClass* Class) void FJsEnvImpl::Bind(FClassWrapper* ClassWrapper, UObject* UEObject, v8::Local JSObject) // Just call in FClassReflection::Call, new a Object { - if (!ClassWrapper->IsNativeTakeJsRef) - { - UserObjectRetainer.Retain(UEObject); - } +#if PUERTS_KEEP_UOBJECT_REFERENCE + const bool IsNativeTakeJsRef = ClassWrapper->IsNativeTakeJsRef; +#else + const bool ClassWrapperIsNativeTakeJsRef = ClassWrapper->IsNativeTakeJsRef; //这个值只有mixin会进行设置 + const bool IsAsset = + UEObject->HasAnyFlags(RF_DefaultSubObject | RF_ClassDefaultObject | RF_ArchetypeObject) || UEObject->IsAsset(); + const bool IsUClass = UEObject->IsA(); + const bool IsNativeTakeJsRef = (IsAsset || IsUClass) ? false : ClassWrapperIsNativeTakeJsRef; +#endif DataTransfer::SetPointer(MainIsolate, JSObject, UEObject, 0); DataTransfer::SetPointer(MainIsolate, JSObject, nullptr, 1); ObjectMap.Emplace(UEObject, v8::UniquePersistent(MainIsolate, JSObject)); - if (!ClassWrapper->IsNativeTakeJsRef) + if (!IsNativeTakeJsRef) { - ObjectMap[UEObject].SetWeak( - (UClass*) ClassWrapper->Struct.Get(), FClassWrapper::OnGarbageCollected, v8::WeakCallbackType::kInternalFields); + SetJsTakeRef(UEObject, ClassWrapper); } } +void FJsEnvImpl::SetJsTakeRef(UObject* UEObject, FClassWrapper* ClassWrapper) +{ + UserObjectRetainer.Retain(UEObject); + ObjectMap[UEObject].SetWeak( + Cast(ClassWrapper->Struct.Get()), FClassWrapper::OnGarbageCollected, v8::WeakCallbackType::kInternalFields); +} + void FJsEnvImpl::UnBind(UClass* Class, UObject* UEObject, bool ResetPointer) { auto PersistentValuePtr = ObjectMap.Find(UEObject); @@ -3012,9 +3045,9 @@ FJsEnvImpl::FTemplateInfo* FJsEnvImpl::GetTemplateInfoOfType(UStruct* InStruct, .ToLocalChecked()); #endif } - +#if PUERTS_KEEP_UOBJECT_REFERENCE StructWrapper->IsNativeTakeJsRef = StructWrapper->IsTypeScriptGeneratedClass = IsTypeScriptGeneratedClass(Class); - +#endif auto SuperClass = Class->GetSuperClass(); if (SuperClass) { @@ -3286,6 +3319,19 @@ void FJsEnvImpl::UEClassToJSClass(const v8::FunctionCallbackInfo& Inf } } +void FJsEnvImpl::SetJsTakeRefInTs(const v8::FunctionCallbackInfo& Info) +{ + v8::Isolate* Isolate = Info.GetIsolate(); + v8::Local Context = Isolate->GetCurrentContext(); + CHECK_V8_ARGS(EArgObject); + + UObject* Object = FV8Utils::GetUObject(Context, Info[0]); + + bool Existed; + auto TemplateInfoPtr = GetTemplateInfoOfType(Object->GetClass(), Existed); + SetJsTakeRef(Object, static_cast(TemplateInfoPtr->StructWrapper.get())); +} + bool FJsEnvImpl::GetContainerTypeProperty(v8::Local Context, v8::Local Value, PropertyMacro** PropertyPtr) { if (Value->IsInt32()) diff --git a/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h b/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h index e60fc83229..50914e1cc2 100644 --- a/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h +++ b/unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h @@ -135,6 +135,8 @@ class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectD public: bool IsTypeScriptGeneratedClass(UClass* Class); + void SetJsTakeRef(UObject* UEObject, FClassWrapper* ClassWrapper); + virtual void Bind(FClassWrapper* ClassWrapper, UObject* UEObject, v8::Local JSObject) override; virtual void UnBind(UClass* Class, UObject* UEObject) override; @@ -281,6 +283,8 @@ class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectD void UEClassToJSClass(const v8::FunctionCallbackInfo& Info); + void SetJsTakeRefInTs(const v8::FunctionCallbackInfo& Info); + bool GetContainerTypeProperty(v8::Local Context, v8::Local Value, PropertyMacro** PropertyPtr); void NewContainer(const v8::FunctionCallbackInfo& Info); diff --git a/unreal/Puerts/Source/JsEnv/Private/StructWrapper.h b/unreal/Puerts/Source/JsEnv/Private/StructWrapper.h index 56fa244fdf..3df6f5bd51 100644 --- a/unreal/Puerts/Source/JsEnv/Private/StructWrapper.h +++ b/unreal/Puerts/Source/JsEnv/Private/StructWrapper.h @@ -87,7 +87,11 @@ class FStructWrapper TWeakObjectPtr Struct; +#if PUERTS_KEEP_UOBJECT_REFERENCE bool IsNativeTakeJsRef = false; +#else + bool IsNativeTakeJsRef = true; +#endif bool IsTypeScriptGeneratedClass = false; diff --git a/unreal/Puerts/Typing/puerts/index.d.ts b/unreal/Puerts/Typing/puerts/index.d.ts index 56ed4b7283..fdb40f9feb 100644 --- a/unreal/Puerts/Typing/puerts/index.d.ts +++ b/unreal/Puerts/Typing/puerts/index.d.ts @@ -89,4 +89,6 @@ declare module "puerts" { } & T function $async(x: T) : AsyncObject;*/ + + function setJsTakeRef(object : Object) : void; } diff --git a/unreal/Puerts/Typing/ue/puerts.d.ts b/unreal/Puerts/Typing/ue/puerts.d.ts index a3479304c3..a28f818c7e 100644 --- a/unreal/Puerts/Typing/ue/puerts.d.ts +++ b/unreal/Puerts/Typing/ue/puerts.d.ts @@ -122,7 +122,7 @@ declare module "ue" { [P in DataPropertyNames]: T[P] extends object ? DataPropertiesOnly : T[P] }; - function NewObject(Cls: Class, Outer?: Object, Name?:string, ObjectFlags?: number): Object; + function NewObject(Cls: Class, Outer?: Object, Name?:string, ObjectFlags?: number, JsTakeRef?: boolean): Object; function NewStruct(St: ScriptStruct): object;