Skip to content

Commit

Permalink
[unreal]在push对象到js的阶段就处理好引用方向(是原生对象引用js,还是js引用原生对象) fix https://githu… (
Browse files Browse the repository at this point in the history
#1217)

* [unreal]在push对象到js的阶段就处理好引用方向(是原生对象引用js,还是js引用原生对象) fix #1205

* 去掉--expose-gc

* [unreal]返回值未使用warning
  • Loading branch information
chexiongsheng authored Feb 24, 2023
1 parent ff7d592 commit c4ca0f8
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 66 deletions.
110 changes: 48 additions & 62 deletions unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,8 +669,6 @@ FJsEnvImpl::~FJsEnvImpl()

ObjectMap.Empty();

GeneratedObjectMap.Empty();

StructCache.Empty();

ContainerCache.Empty();
Expand Down Expand Up @@ -1271,18 +1269,15 @@ void FJsEnvImpl::MakeSureInject(UTypeScriptGeneratedClass* TypeScriptGeneratedCl
for (FUEObjectIterator It(TypeScriptGeneratedClass); It; ++It)
{
auto Object = *It;
if (GeneratedObjectMap.Find(Object))
if (ObjectMap.Find(Object))
continue;
if (Object->GetClass()->GetName().StartsWith(TEXT("REINST_")))
continue; //跳过父类重新编译后临时状态的对象
//在编辑器下重启虚拟机,如果TS带构造函数,不重新执行的话,新虚拟机上逻辑上少执行了逻辑(比如对js对象一些字段的初始化)
//执行的话,对CreateDefaultSubobject这类UE逻辑又不允许执行多次(会崩溃),两者相较取其轻
//后面看是否能参照蓝图的组件初始化进行改造
// TsConstruct(TypeScriptGeneratedClass, Object);
auto JSObject =
FindOrAdd(Isolate, Context, Object->GetClass(), Object)->ToObject(Context).ToLocalChecked();
GeneratedObjectMap.Emplace(Object, v8::UniquePersistent<v8::Value>(MainIsolate, JSObject));
UnBind(TypeScriptGeneratedClass, Object);
__USE(FindOrAdd(Isolate, Context, Object->GetClass(), Object));
}
}

Expand Down Expand Up @@ -1559,14 +1554,37 @@ FString FJsEnvImpl::CurrentStackTrace()
#endif
}

void FJsEnvImpl::Bind(
UClass* Class, UObject* UEObject, v8::Local<v8::Object> JSObject) // Just call in FClassReflection::Call, new a Object
bool FJsEnvImpl::IsNativeTakeJsRef(UClass* Class)
{
while (Class)
{
if (Class->GetClass() == UTypeScriptGeneratedClass::StaticClass())
{
return true;
}

Class = Class->GetSuperClass();
}
return false;
}

void FJsEnvImpl::Bind(FClassWrapper* ClassWrapper, UObject* UEObject,
v8::Local<v8::Object> JSObject) // Just call in FClassReflection::Call, new a Object
{
UserObjectRetainer.Retain(UEObject);
if (!ClassWrapper->IsNativeTakeJsRef)
{
UserObjectRetainer.Retain(UEObject);
}

DataTransfer::SetPointer(MainIsolate, JSObject, UEObject, 0);
DataTransfer::SetPointer(MainIsolate, JSObject, nullptr, 1);
ObjectMap.Emplace(UEObject, v8::UniquePersistent<v8::Value>(MainIsolate, JSObject));
ObjectMap[UEObject].SetWeak<UClass>(Class, FClassWrapper::OnGarbageCollected, v8::WeakCallbackType::kInternalFields);

if (!ClassWrapper->IsNativeTakeJsRef)
{
ObjectMap[UEObject].SetWeak<UClass>(
(UClass*) ClassWrapper->Struct.Get(), FClassWrapper::OnGarbageCollected, v8::WeakCallbackType::kInternalFields);
}
}

void FJsEnvImpl::UnBind(UClass* Class, UObject* UEObject, bool ResetPointer)
Expand All @@ -1582,7 +1600,9 @@ void FJsEnvImpl::UnBind(UClass* Class, UObject* UEObject, bool ResetPointer)
auto Context = DefaultContext.Get(Isolate);
v8::Context::Scope ContextScope(Context);

DataTransfer::SetPointer(MainIsolate, PersistentValuePtr->Get(Isolate).As<v8::Object>(), RELEASED_UOBJECT, 0);
auto JsObject = PersistentValuePtr->Get(Isolate).As<v8::Object>();
DataTransfer::SetPointer(MainIsolate, JsObject, RELEASED_UOBJECT, 0);
DataTransfer::SetPointer(Isolate, JsObject, nullptr, 1);
}
ObjectMap.Remove(UEObject);
UserObjectRetainer.Release(UEObject);
Expand All @@ -1604,11 +1624,6 @@ v8::Local<v8::Value> FJsEnvImpl::FindOrAdd(v8::Isolate* Isolate, v8::Local<v8::C
auto PersistentValuePtr = ObjectMap.Find(UEObject);
if (!PersistentValuePtr) // create and link
{
auto PersistentValuePtr2 = GeneratedObjectMap.Find(UEObject);
if (PersistentValuePtr2) // TODO: 后续尝试改为新建一个对象,这个对象持有UObject的引用,并且把调用转发到Iter2->second
{
return v8::Local<v8::Value>::New(Isolate, *PersistentValuePtr2);
}
auto BindTo = v8::External::New(Context->GetIsolate(), UEObject);
v8::Handle<v8::Value> Args[] = {BindTo};
return GetJsClass(Class, Context)->NewInstance(Context, 1, Args).ToLocalChecked();
Expand Down Expand Up @@ -1781,8 +1796,9 @@ void FJsEnvImpl::JsConstruct(UClass* Class, UObject* Object, const v8::UniquePer
v8::TryCatch TryCatch(Isolate);

auto JSObject = FindOrAdd(Isolate, Context, Class, Object)->ToObject(Context).ToLocalChecked();
GeneratedObjectMap.Emplace(Object, v8::UniquePersistent<v8::Value>(MainIsolate, JSObject));
// 过时功能(makeUClass)用不影响现有功能的方式修改
UnBind(Class, Object);
ObjectMap.Emplace(Object, v8::UniquePersistent<v8::Value>(MainIsolate, JSObject));

if (!Prototype.IsEmpty())
{
Expand Down Expand Up @@ -1856,12 +1872,10 @@ void FJsEnvImpl::TsConstruct(UTypeScriptGeneratedClass* Class, UObject* Object)
v8::TryCatch TryCatch(Isolate);

v8::Local<v8::Object> JSObject;
auto PersistentValuePtr = GeneratedObjectMap.Find(Object);
auto PersistentValuePtr = ObjectMap.Find(Object);
if (!PersistentValuePtr)
{
JSObject = FindOrAdd(Isolate, Context, Object->GetClass(), Object)->ToObject(Context).ToLocalChecked();
GeneratedObjectMap.Emplace(Object, v8::UniquePersistent<v8::Value>(MainIsolate, JSObject));
UnBind(Class, Object);

// FindOrAdd may change BindInfoMap, cause a rehash
BindInfoPtr = BindInfoMap.Find(Class);
Expand Down Expand Up @@ -1901,21 +1915,6 @@ void FJsEnvImpl::NotifyUObjectDeleted(const class UObjectBase* ObjectBase, int32
#ifdef THREAD_SAFE
v8::Locker Locker(MainIsolate);
#endif
auto PersistentValuePtr = GeneratedObjectMap.Find(ObjectBase);
if (PersistentValuePtr)
{
// UE_LOG(LogTemp, Warning, TEXT("NotifyUObjectDeleted: %s(%p)"), *ObjectBase->GetClass()->GetName(), Object);
auto Isolate = MainIsolate;
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
auto Context = v8::Local<v8::Context>::New(Isolate, DefaultContext);
v8::Context::Scope ContextScope(Context);

auto JSObject = PersistentValuePtr->Get(Isolate)->ToObject(Context).ToLocalChecked();
DataTransfer::SetPointer(Isolate, JSObject, RELEASED_UOBJECT, 0);
DataTransfer::SetPointer(Isolate, JSObject, nullptr, 1);
GeneratedObjectMap.Remove(ObjectBase);
}

TryReleaseType((UStruct*) ObjectBase);

Expand Down Expand Up @@ -2003,7 +2002,7 @@ void FJsEnvImpl::InvokeJsMethod(UObject* ContextObject, UJSGeneratedFunction* Fu
v8::Context::Scope ContextScope(Context);

v8::Local<v8::Value> Self;
auto GeneratedObjectPtr = GeneratedObjectMap.Find(ContextObject);
auto GeneratedObjectPtr = ObjectMap.Find(ContextObject);
if (GeneratedObjectPtr)
{
Self = GeneratedObjectPtr->Get(Isolate);
Expand Down Expand Up @@ -2043,26 +2042,7 @@ void FJsEnvImpl::InvokeMixinMethod(UObject* ContextObject, UJSGeneratedFunction*
auto Context = DefaultContext.Get(Isolate);
v8::Context::Scope ContextScope(Context);

v8::Local<v8::Value> Self;

if (Function->TakeJsObjectRef)
{
auto GeneratedObjectPtr = GeneratedObjectMap.Find(ContextObject);
if (GeneratedObjectPtr)
{
Self = GeneratedObjectPtr->Get(Isolate);
}
else
{
Self = FindOrAdd(Isolate, Context, ContextObject->GetClass(), ContextObject)->ToObject(Context).ToLocalChecked();
GeneratedObjectMap.Emplace(ContextObject, v8::UniquePersistent<v8::Value>(MainIsolate, Self));
UnBind(ContextObject->GetClass(), ContextObject);
}
}
else
{
Self = FindOrAdd(Isolate, Context, ContextObject->GetClass(), ContextObject);
}
v8::Local<v8::Value> Self = FindOrAdd(Isolate, Context, ContextObject->GetClass(), ContextObject);

auto JsFuncPtr = MixinFunctionMap.Find(Function);
if (!JsFuncPtr)
Expand Down Expand Up @@ -2112,7 +2092,7 @@ void FJsEnvImpl::InvokeTsMethod(UObject* ContextObject, UFunction* Function, FFr

if (!Function->HasAnyFunctionFlags(FUNC_Static))
{
const auto PersistentValuePtr = GeneratedObjectMap.Find(ContextObject);
const auto PersistentValuePtr = ObjectMap.Find(ContextObject);
if (!PersistentValuePtr)
{
Logger->Error(FString::Printf(TEXT("call %s::%s of %p fail: can not find Binded JavaScript Object"),
Expand Down Expand Up @@ -2166,13 +2146,11 @@ void FJsEnvImpl::NotifyReBind(UTypeScriptGeneratedClass* Class)
for (TWeakObjectPtr<UObject>& Iter : Class->GeneratedObjects)
{
auto Object = Iter.Get();
if (!Object || GeneratedObjectMap.Find(Object))
if (!Object || ObjectMap.Find(Object))
continue;
if (Object->GetClass()->GetName().StartsWith(TEXT("REINST_")))
continue; //跳过父类重新编译后临时状态的对象
auto JSObject = FindOrAdd(Isolate, Context, Object->GetClass(), Object)->ToObject(Context).ToLocalChecked();
GeneratedObjectMap.Emplace(Object, v8::UniquePersistent<v8::Value>(MainIsolate, JSObject));
UnBind(Class, Object);
__USE(FindOrAdd(Isolate, Context, Object->GetClass(), Object));
}
}
#endif
Expand Down Expand Up @@ -2801,6 +2779,8 @@ v8::Local<v8::FunctionTemplate> FJsEnvImpl::GetTemplateOfClass(UStruct* InStruct
#endif
}

StructWrapper->IsNativeTakeJsRef = IsNativeTakeJsRef(Class);

auto SuperClass = Class->GetSuperClass();
if (SuperClass)
{
Expand Down Expand Up @@ -4021,6 +4001,12 @@ void FJsEnvImpl::Mixin(const v8::FunctionCallbackInfo<v8::Value>& Info)
}
}
MixinClasses.Add(New);

bool Existed = false;
GetTemplateOfClass(New, Existed);
bool IsReuseTemplate = false;
auto StructWrapper = GetStructWrapper(New, IsReuseTemplate);
StructWrapper->IsNativeTakeJsRef = TakeJsObjectRef;
Info.GetReturnValue().Set(FindOrAdd(Isolate, Context, New->GetClass(), New));
}
#endif
Expand Down
5 changes: 3 additions & 2 deletions unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectD
virtual void OnSourceLoaded(std::function<void(const FString&)> Callback) override;

public:
virtual void Bind(UClass* Class, UObject* UEObject, v8::Local<v8::Object> JSObject) override;
bool IsNativeTakeJsRef(UClass* Class);

virtual void Bind(FClassWrapper* ClassWrapper, UObject* UEObject, v8::Local<v8::Object> JSObject) override;

virtual void UnBind(UClass* Class, UObject* UEObject) override;

Expand Down Expand Up @@ -503,7 +505,6 @@ class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectD
TMap<FString, std::shared_ptr<FStructWrapper>> TypeReflectionMap;

TMap<UObject*, v8::UniquePersistent<v8::Value>> ObjectMap;
TMap<const class UObjectBase*, v8::UniquePersistent<v8::Value>> GeneratedObjectMap;

TMap<void*, FObjectCacheNode> StructCache;

Expand Down
2 changes: 1 addition & 1 deletion unreal/Puerts/Source/JsEnv/Private/ObjectMapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class ICppObjectMapper
class IObjectMapper : public ICppObjectMapper
{
public:
virtual void Bind(UClass* Class, UObject* UEObject, v8::Local<v8::Object> JSObject) = 0;
virtual void Bind(FClassWrapper* ClassWrapper, UObject* UEObject, v8::Local<v8::Object> JSObject) = 0;

virtual void UnBind(UClass* Class, UObject* UEObject) = 0;

Expand Down
2 changes: 1 addition & 1 deletion unreal/Puerts/Source/JsEnv/Private/StructWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ void FClassWrapper::New(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, c
Object = NewObject<UObject>(Outer, Class, Name, ObjectFlags);
}

FV8Utils::IsolateData<IObjectMapper>(Isolate)->Bind(Class, Object, Self);
FV8Utils::IsolateData<IObjectMapper>(Isolate)->Bind(this, Object, Self);
}
else
{
Expand Down
2 changes: 2 additions & 0 deletions unreal/Puerts/Source/JsEnv/Private/StructWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class FStructWrapper

TWeakObjectPtr<UStruct> Struct;

bool IsNativeTakeJsRef = false;

static void StaticClass(const v8::FunctionCallbackInfo<v8::Value>& Info);

static void Find(const v8::FunctionCallbackInfo<v8::Value>& Info);
Expand Down

0 comments on commit c4ca0f8

Please sign in to comment.