Skip to content

Commit

Permalink
[unreal]支持在被绑定的C++代码中抛js异常(默认关闭,需要通过定义WITH_JS_THROW_IN_CPP打开)
Browse files Browse the repository at this point in the history
  • Loading branch information
chexiongsheng committed Oct 31, 2023
1 parent ebca7d4 commit e06b967
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
5 changes: 5 additions & 0 deletions unreal/Puerts/Source/JsEnv/Public/ScriptBackend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,9 @@ ClassDefineBuilder<T, PUERTS_BINDING_IMPL::API, PUERTS_BINDING_IMPL::API> Define
using Object = PUERTS_BINDING_IMPL::Object;

using Function = PUERTS_BINDING_IMPL::Function;

inline void ThrowException(const char* msg)
{
internal::ExceptionHandle<PUERTS_BINDING_IMPL::API>::Throw(msg);
}
} // namespace PUERTS_NAMESPACE
59 changes: 59 additions & 0 deletions unreal/Puerts/Source/JsEnv/Public/StaticCall.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,62 @@ struct ArgumentChecker<API, Pos, StopPos, ArgType, Rest...>
}
};

template <typename API, typename Enable = void>
struct ExceptionHandle;

template <typename API>
struct ExceptionHandle<API, typename std::enable_if<std::is_pointer<typename API::CallbackInfoType>::value>::type>
{
static void SetCallbackInfoOrThrow(typename API::CallbackInfoType info, const char* error_msg)
{
#if defined(WITH_JS_THROW_IN_CPP)
thread_local typename API::CallbackInfoType s_info;
if (error_msg)
{
API::ThrowException(s_info, error_msg);
}
else
{
s_info = info;
}
#endif
}

static void Throw(const char* error_msg)
{
#if defined(WITH_JS_THROW_IN_CPP)
SetCallbackInfoOrThrow(nullptr, error_msg);
#endif
}
};

template <typename API>
struct ExceptionHandle<API, typename std::enable_if<!std::is_pointer<typename API::CallbackInfoType>::value>::type>
{
static void SetCallbackInfoOrThrow(typename API::CallbackInfoType info, const char* error_msg)
{
#if defined(WITH_JS_THROW_IN_CPP)
thread_local std::decay<typename API::CallbackInfoType>::type* s_info;
if (error_msg)
{
API::ThrowException(*s_info, error_msg);
}
else
{
s_info = (std::decay<typename API::CallbackInfoType>::type*) &info;
}
#endif
}

static void Throw(const char* error_msg)
{
#if defined(WITH_JS_THROW_IN_CPP)
thread_local std::decay<typename API::CallbackInfoType>::type* pinfo = nullptr;
SetCallbackInfoOrThrow(*pinfo, error_msg);
#endif
}
};

template <typename, typename, bool, bool, bool, bool>
struct FuncCallHelper
{
Expand Down Expand Up @@ -718,13 +774,15 @@ struct FuncCallHelper<API, std::pair<Ret, std::tuple<Args...>>, CheckArguments,
static bool call(Func&& func, typename API::CallbackInfoType info, DefaultArguments&&... defaultValues)
{
static_assert(sizeof...(Args) >= sizeof...(DefaultArguments), "too many default arguments");
ExceptionHandle<API>::SetCallbackInfoOrThrow(info, nullptr);
return call(func, info, std::make_index_sequence<ArgsLength>(), std::forward<DefaultArguments>(defaultValues)...);
}

template <typename Ins, typename Func, class... DefaultArguments>
static bool callMethod(Func&& func, typename API::CallbackInfoType info, DefaultArguments&&... defaultValues)
{
static_assert(sizeof...(Args) >= sizeof...(DefaultArguments), "too many default arguments");
ExceptionHandle<API>::SetCallbackInfoOrThrow(info, nullptr);
return callMethod<Ins>(
func, info, std::make_index_sequence<ArgsLength>(), std::forward<DefaultArguments>(defaultValues)...);
}
Expand All @@ -733,6 +791,7 @@ struct FuncCallHelper<API, std::pair<Ret, std::tuple<Args...>>, CheckArguments,
static bool callExtension(Func&& func, typename API::CallbackInfoType info, DefaultArguments&&... defaultValues)
{
static_assert(sizeof...(Args) >= sizeof...(DefaultArguments), "too many default arguments");
ExceptionHandle<API>::SetCallbackInfoOrThrow(info, nullptr);
return callExtension<Ins>(
func, info, std::make_index_sequence<ArgsLength>(), std::forward<DefaultArguments>(defaultValues)...);
}
Expand Down

0 comments on commit e06b967

Please sign in to comment.