Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions unreal/Puerts/Content/JavaScript/puerts/uelazyload.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ var global = global || (function () { return this; }());
rawSet(UE, 'NewStruct', global.__tgjsNewStruct);
global.__tgjsNewStruct = undefined;

rawSet(UE, 'MakeWeakObjectPtr', global.__tgjsMakeWeakObjectPtr);
global.__tgjsMakeWeakObjectPtr = undefined;

puerts.$ref = ref;
puerts.$unref = unref;
puerts.$set = setref;
Expand Down
40 changes: 40 additions & 0 deletions unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "DelegateWrapper.h"
#include "ContainerWrapper.h"
#include "SoftObjectWrapper.h"
#include "WeakObjectPtrWrapper.h"
#include "V8Utils.h"
#include "ObjectMapper.h"
#include "JSLogger.h"
Expand Down Expand Up @@ -515,6 +516,8 @@ FJsEnvImpl::FJsEnvImpl(std::shared_ptr<IJSModuleLoader> InModuleLoader, std::sha

MethodBindingHelper<&FJsEnvImpl::NewStructByScriptStruct>::Bind(Isolate, Context, Global, "__tgjsNewStruct", This);

MethodBindingHelper<&FJsEnvImpl::MakeWeakObjectPtr>::Bind(Isolate, Context, Global, "__tgjsMakeWeakObjectPtr", This);

#if !defined(ENGINE_INDEPENDENT_JSENV)
MethodBindingHelper<&FJsEnvImpl::MakeUClass>::Bind(Isolate, Context, Global, "__tgjsMakeUClass", This);

Expand Down Expand Up @@ -610,6 +613,9 @@ FJsEnvImpl::FJsEnvImpl(std::shared_ptr<IJSModuleLoader> InModuleLoader, std::sha

SoftObjectPtrTemplate = v8::UniquePersistent<v8::FunctionTemplate>(Isolate, FSoftObjectWrapper::ToFunctionTemplate(Isolate));

WeakObjectPtrTemplate =
v8::UniquePersistent<v8::FunctionTemplate>(Isolate, FWeakObjectPtrWrapper::ToFunctionTemplate(Isolate));

DynamicInvoker = MakeShared<DynamicInvokerImpl, ESPMode::ThreadSafe>(this);
MixinInvoker = DynamicInvoker;
#if !defined(ENGINE_INDEPENDENT_JSENV)
Expand Down Expand Up @@ -870,6 +876,7 @@ FJsEnvImpl::~FJsEnvImpl()
DynamicInvoker.Reset();
MixinInvoker.Reset();

WeakObjectPtrTemplate.Reset();
SoftObjectPtrTemplate.Reset();
MulticastDelegateTemplate.Reset();
DelegateTemplate.Reset();
Expand Down Expand Up @@ -1144,6 +1151,39 @@ void FJsEnvImpl::NewStructByScriptStruct(const v8::FunctionCallbackInfo<v8::Valu
}
}

void FJsEnvImpl::MakeWeakObjectPtr(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
v8::Isolate* Isolate = Info.GetIsolate();
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
v8::Local<v8::Context> Context = Isolate->GetCurrentContext();
v8::Context::Scope ContextScope(Context);

UObject* Object = reinterpret_cast<UObject*>(FV8Utils::GetPointer(Context, Info[0]));
if (FV8Utils::IsReleasedPtr(Object))
{
Object = nullptr;
}

TWeakObjectPtr<UObject>* WeakPtr = new TWeakObjectPtr<UObject>(Object);

const auto JSObject = WeakObjectPtrTemplate.Get(Isolate)->InstanceTemplate()->NewInstance(Context).ToLocalChecked();
DataTransfer::SetPointer(Isolate, JSObject, WeakPtr, 0);

v8::Global<v8::Object>* GlobalPtr = new v8::Global<v8::Object>(Isolate, JSObject);
GlobalPtr->SetWeak<v8::Global<v8::Object>>(
GlobalPtr,
[](const v8::WeakCallbackInfo<v8::Global<v8::Object>>& Data)
{
void* Ptr = DataTransfer::MakeAddressWithHighPartOfTwo(Data.GetInternalField(0), Data.GetInternalField(1));
delete static_cast<TWeakObjectPtr<UObject>*>(Ptr);
delete Data.GetParameter();
},
v8::WeakCallbackType::kInternalFields);

Info.GetReturnValue().Set(JSObject);
}

bool FJsEnvImpl::IdleNotificationDeadline(double DeadlineInSeconds)
{
#ifdef THREAD_SAFE
Expand Down
4 changes: 4 additions & 0 deletions unreal/Puerts/Source/JsEnv/Private/JsEnvImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectD

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

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

#if !defined(ENGINE_INDEPENDENT_JSENV)
void MakeUClass(const v8::FunctionCallbackInfo<v8::Value>& Info);

Expand Down Expand Up @@ -694,6 +696,8 @@ class FJsEnvImpl : public IJsEnv, IObjectMapper, public FUObjectArray::FUObjectD

v8::UniquePersistent<v8::FunctionTemplate> SoftObjectPtrTemplate;

v8::UniquePersistent<v8::FunctionTemplate> WeakObjectPtrTemplate;

std::map<void*, DelegateObjectInfo> DelegateMap;

TMap<UFunction*, TsFunctionInfo> TsFunctionMap;
Expand Down
55 changes: 55 additions & 0 deletions unreal/Puerts/Source/JsEnv/Private/WeakObjectPtrWrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "WeakObjectPtrWrapper.h"
#include "V8Utils.h"
#include "ObjectMapper.h"

namespace PUERTS_NAMESPACE
{
v8::Local<v8::FunctionTemplate> FWeakObjectPtrWrapper::ToFunctionTemplate(v8::Isolate* Isolate)
{
auto Result = v8::FunctionTemplate::New(Isolate);
Result->InstanceTemplate()->SetInternalFieldCount(4);
Result->PrototypeTemplate()->Set(FV8Utils::ToV8String(Isolate, "Get"), v8::FunctionTemplate::New(Isolate, &Get));
Result->PrototypeTemplate()->Set(FV8Utils::ToV8String(Isolate, "IsValid"), v8::FunctionTemplate::New(Isolate, &IsValid));
return Result;
}

void FWeakObjectPtrWrapper::Get(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
auto Isolate = Info.GetIsolate();
auto Context = Isolate->GetCurrentContext();

TWeakObjectPtr<UObject>* Ptr = FV8Utils::GetPointerFast<TWeakObjectPtr<UObject>>(Info.Holder());
if (!Ptr)
{
FV8Utils::ThrowException(Isolate, "invalid weak object ptr wrapper");
return;
}

UObject* Obj = Ptr->Get();
if (Obj && Obj->IsValidLowLevelFast() && !UEObjectIsPendingKill(Obj))
{
Info.GetReturnValue().Set(
FV8Utils::IsolateData<IObjectMapper>(Isolate)->FindOrAdd(Isolate, Context, Obj->GetClass(), Obj));
}
else
{
Info.GetReturnValue().Set(v8::Undefined(Isolate));
}
}

void FWeakObjectPtrWrapper::IsValid(const v8::FunctionCallbackInfo<v8::Value>& Info)
{
auto Isolate = Info.GetIsolate();

TWeakObjectPtr<UObject>* Ptr = FV8Utils::GetPointerFast<TWeakObjectPtr<UObject>>(Info.Holder());
if (!Ptr)
{
Info.GetReturnValue().Set(v8::Boolean::New(Isolate, false));
return;
}

UObject* Obj = Ptr->Get();
bool bValid = Obj && Obj->IsValidLowLevelFast() && !UEObjectIsPendingKill(Obj);
Info.GetReturnValue().Set(v8::Boolean::New(Isolate, bValid));
}
} // namespace PUERTS_NAMESPACE
34 changes: 34 additions & 0 deletions unreal/Puerts/Source/JsEnv/Private/WeakObjectPtrWrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Tencent is pleased to support the open source community by making Puerts available.
* Copyright (C) 2020 Tencent. 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

#include "CoreMinimal.h"

#include "NamespaceDef.h"

PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
#pragma warning(push, 0)
#include "libplatform/libplatform.h"
#include "v8.h"
#pragma warning(pop)
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS

namespace PUERTS_NAMESPACE
{
class FWeakObjectPtrWrapper
{
public:
static v8::Local<v8::FunctionTemplate> ToFunctionTemplate(v8::Isolate* Isolate);

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

static void IsValid(const v8::FunctionCallbackInfo<v8::Value>& Info);
};
} // namespace PUERTS_NAMESPACE
7 changes: 7 additions & 0 deletions unreal/Puerts/Typing/ue/puerts.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,13 @@ declare module "ue" {
function NewStruct(St: ScriptStruct): object;

function FNameLiteral(str:string):string;

interface WeakObjectPtr<T> {
Get(): T | undefined;
IsValid(): boolean;
}

function MakeWeakObjectPtr<T extends Object>(obj: T): WeakObjectPtr<T>;

type TWeakObjectPtr<T> = {
[K in keyof T]: T[K];
Expand Down
Loading