Skip to content

Commit

Permalink
[unreal]简化实现
Browse files Browse the repository at this point in the history
  • Loading branch information
chexiongsheng committed Jul 30, 2021
1 parent e52bbe7 commit a000310
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 191 deletions.
2 changes: 1 addition & 1 deletion unreal/Puerts/Source/JsEnv/Private/JSLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "JSLogger.h"

DEFINE_LOG_CATEGORY_STATIC(Puerts, Log, All);
DEFINE_LOG_CATEGORY(Puerts);

namespace puerts
{
Expand Down
4 changes: 2 additions & 2 deletions unreal/Puerts/Source/JsEnv/Public/JSLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#pragma once

#include "CoreMinimal.h"
#include <functional>
#include <memory>

DECLARE_LOG_CATEGORY_EXTERN(Puerts, Log, All);

namespace puerts
{
Expand Down
364 changes: 176 additions & 188 deletions unreal/Puerts/Source/JsEnv/Public/JsObject.h
Original file line number Diff line number Diff line change
@@ -1,188 +1,176 @@
/*
* 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

#pragma warning(push, 0)
#include "v8.h"
#pragma warning(pop)

#include "Binding.hpp"
#include "JSLogger.h"
#include "V8Utils.h"

#include "CoreMinimal.h"
#include "JsObject.generated.h"

USTRUCT(BlueprintType)
struct FJsObject
{
public:
GENERATED_USTRUCT_BODY()

FJsObject():Isolate(nullptr){}

FJsObject(const FJsObject & InOther)
{
Isolate = InOther.Isolate;
GContext.Reset(Isolate, InOther.GContext.Get(Isolate));
GObject.Reset(Isolate, InOther.GObject.Get(Isolate));
}

FJsObject(v8::Local<v8::Context> InContext, v8::Local<v8::Object> InObject)
: Isolate(InContext->GetIsolate()),
GContext(InContext->GetIsolate(), InContext),
GObject(InContext->GetIsolate(), InObject)
{}

FJsObject & operator =(const FJsObject & InOther)
{
Isolate = InOther.Isolate;
GContext.Reset(Isolate, InOther.GContext.Get(Isolate));
GObject.Reset(Isolate, InOther.GObject.Get(Isolate));
return *this;
}

template<typename T>
T Get(const char* Key)
{
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
auto Context = GContext.Get(Isolate);
v8::Context::Scope ContextScope(Context);
auto Object = GObject.Get(Isolate);

auto MaybeValue = Object->Get(Context, puerts::converter::Converter<const char*>::toScript(Context, Key));
v8::Local<v8::Value> Val;
if (MaybeValue.ToLocal(&Val))
{
return puerts::converter::Converter<T>::toCpp(Context, Val);
}
return {};
}

template<typename T>
void Set(const char* Key, T Val)
{
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
auto Context = GContext.Get(Isolate);
v8::Context::Scope ContextScope(Context);
auto Object = GObject.Get(Isolate);

auto _UnUsed = Object->Set(Context, puerts::converter::Converter<const char*>::toScript(Context, Key),
puerts::converter::Converter<T>::toScript(Context, Val));
}

void SetLogger(std::shared_ptr<puerts::ILogger> InLogger)
{
Logger = InLogger;
}

template<typename... Args>
void Action(Args... cppArgs)
{
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
auto Context = GContext.Get(Isolate);
v8::Context::Scope ContextScope(Context);

auto Object = GObject.Get(Isolate);

if (!Object->IsFunction())
{
if (Logger) Logger->Error(TEXT("call a non-function object!"));
return;
}

v8::TryCatch TryCatch(Isolate);

v8::Local<v8::Value> Argv[sizeof...(Args)] {puerts::converter::Converter<Args>::toScript(Context, cppArgs)...};
auto _UnUsed = Object.As<v8::Function>()->Call(Context, v8::Undefined(Isolate), sizeof...(Args), Argv);

if (TryCatch.HasCaught())
{
if (Logger)
{
Logger->Error(FString::Printf(TEXT("call function throw: %s"), *puerts::FV8Utils::TryCatchToString(Isolate, &TryCatch)));
}
}
}

template<typename Ret, typename... Args>
Ret Func(Args... cppArgs)
{
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
auto Context = GContext.Get(Isolate);
v8::Context::Scope ContextScope(Context);

auto Object = GObject.Get(Isolate);

if (!Object->IsFunction())
{
if (Logger) Logger->Error(TEXT("call a non-function object!"));
return {};
}

v8::TryCatch TryCatch(Isolate);

v8::Local<v8::Value> Argv[sizeof...(Args)] {puerts::converter::Converter<Args>::toScript(Context, cppArgs)...};
auto MaybeRet = Object.As<v8::Function>()->Call(Context, v8::Undefined(Isolate), sizeof...(Args), Argv);

if (TryCatch.HasCaught())
{
if (Logger)
{
Logger->Error(FString::Printf(TEXT("call function throw: %s"), *puerts::FV8Utils::TryCatchToString(Isolate, &TryCatch)));
}
}

if (!MaybeRet.IsEmpty())
{
return puerts::converter::Converter<Ret>::toCpp(Context, MaybeRet.ToLocalChecked());
}
return {};
}

private:
v8::Isolate *Isolate;
v8::Global<v8::Context> GContext;
v8::Global<v8::Object> GObject;
std::shared_ptr<puerts::ILogger> Logger;

friend struct puerts::converter::Converter<FJsObject>;
};

namespace puerts
{
template<>
struct ScriptTypeName<FJsObject> {
static constexpr const char * value = "object";
};

namespace converter
{
template <>
struct Converter<FJsObject> {
static v8::Local<v8::Value> toScript(v8::Local<v8::Context> context, FJsObject value)
{
return value.GObject.Get(context->GetIsolate());
}

static FJsObject toCpp(v8::Local<v8::Context> context, const v8::Local<v8::Value>& value)
{
return FJsObject(context, value.As<v8::Object>());
}

static bool accept(v8::Local<v8::Context> context, const v8::Local<v8::Value>& value)
{
return value->IsObject();
}
};
}
}
/*
* 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

#pragma warning(push, 0)
#include "v8.h"
#pragma warning(pop)

#include "Binding.hpp"
#include "JSLogger.h"
#include "V8Utils.h"

#include "CoreMinimal.h"
#include "JsObject.generated.h"

USTRUCT(BlueprintType)
struct FJsObject
{
public:
GENERATED_USTRUCT_BODY()

FJsObject():Isolate(nullptr){}

FJsObject(const FJsObject & InOther)
{
Isolate = InOther.Isolate;
GContext.Reset(Isolate, InOther.GContext.Get(Isolate));
GObject.Reset(Isolate, InOther.GObject.Get(Isolate));
}

FJsObject(v8::Local<v8::Context> InContext, v8::Local<v8::Object> InObject)
: Isolate(InContext->GetIsolate()),
GContext(InContext->GetIsolate(), InContext),
GObject(InContext->GetIsolate(), InObject)
{}

FJsObject & operator =(const FJsObject & InOther)
{
Isolate = InOther.Isolate;
GContext.Reset(Isolate, InOther.GContext.Get(Isolate));
GObject.Reset(Isolate, InOther.GObject.Get(Isolate));
return *this;
}

template<typename T>
T Get(const char* Key)
{
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
auto Context = GContext.Get(Isolate);
v8::Context::Scope ContextScope(Context);
auto Object = GObject.Get(Isolate);

auto MaybeValue = Object->Get(Context, puerts::converter::Converter<const char*>::toScript(Context, Key));
v8::Local<v8::Value> Val;
if (MaybeValue.ToLocal(&Val))
{
return puerts::converter::Converter<T>::toCpp(Context, Val);
}
return {};
}

template<typename T>
void Set(const char* Key, T Val)
{
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
auto Context = GContext.Get(Isolate);
v8::Context::Scope ContextScope(Context);
auto Object = GObject.Get(Isolate);

auto _UnUsed = Object->Set(Context, puerts::converter::Converter<const char*>::toScript(Context, Key),
puerts::converter::Converter<T>::toScript(Context, Val));
}

template<typename... Args>
void Action(Args... cppArgs)
{
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
auto Context = GContext.Get(Isolate);
v8::Context::Scope ContextScope(Context);

auto Object = GObject.Get(Isolate);

if (!Object->IsFunction())
{
UE_LOG(Puerts, Error, TEXT("call a non-function object!"));
return {};
}

v8::TryCatch TryCatch(Isolate);

v8::Local<v8::Value> Argv[sizeof...(Args)] {puerts::converter::Converter<Args>::toScript(Context, cppArgs)...};
auto _UnUsed = Object.As<v8::Function>()->Call(Context, v8::Undefined(Isolate), sizeof...(Args), Argv);

if (TryCatch.HasCaught())
{
UE_LOG(Puerts, Error, TEXT("call function throw: %s"), *puerts::FV8Utils::TryCatchToString(Isolate, &TryCatch));
}
}

template<typename Ret, typename... Args>
Ret Func(Args... cppArgs)
{
v8::Isolate::Scope IsolateScope(Isolate);
v8::HandleScope HandleScope(Isolate);
auto Context = GContext.Get(Isolate);
v8::Context::Scope ContextScope(Context);

auto Object = GObject.Get(Isolate);

if (!Object->IsFunction())
{
UE_LOG(Puerts, Error, TEXT("call a non-function object!"));
return {};
}

v8::TryCatch TryCatch(Isolate);

v8::Local<v8::Value> Argv[sizeof...(Args)] {puerts::converter::Converter<Args>::toScript(Context, cppArgs)...};
auto MaybeRet = Object.As<v8::Function>()->Call(Context, v8::Undefined(Isolate), sizeof...(Args), Argv);

if (TryCatch.HasCaught())
{
UE_LOG(Puerts, Error, TEXT("call function throw: %s"), *puerts::FV8Utils::TryCatchToString(Isolate, &TryCatch));
}

if (!MaybeRet.IsEmpty())
{
return puerts::converter::Converter<Ret>::toCpp(Context, MaybeRet.ToLocalChecked());
}
return {};
}

private:
v8::Isolate *Isolate;
v8::Global<v8::Context> GContext;
v8::Global<v8::Object> GObject;

friend struct puerts::converter::Converter<FJsObject>;
};

namespace puerts
{
template<>
struct ScriptTypeName<FJsObject> {
static constexpr const char * value = "object";
};

namespace converter
{
template <>
struct Converter<FJsObject> {
static v8::Local<v8::Value> toScript(v8::Local<v8::Context> context, FJsObject value)
{
return value.GObject.Get(context->GetIsolate());
}

static FJsObject toCpp(v8::Local<v8::Context> context, const v8::Local<v8::Value>& value)
{
return FJsObject(context, value.As<v8::Object>());
}

static bool accept(v8::Local<v8::Context> context, const v8::Local<v8::Value>& value)
{
return value->IsObject();
}
};
}
}

0 comments on commit a000310

Please sign in to comment.