15 #ifndef SHAKA_EMBEDDED_MAPPING_REGISTER_MEMBER_H_ 16 #define SHAKA_EMBEDDED_MAPPING_REGISTER_MEMBER_H_ 19 #include <type_traits> 58 # define SET_RETURN_VALUE(args, value) (args).GetReturnValue().Set(value) 59 # define SET_EXCEPTION(args, except) GetIsolate()->ThrowException(except) 60 # define GET_ARG_THIS(args) (static_cast<v8::Local<v8::Value>>((args).This())) 61 #elif defined(USING_JSC) 62 # define SET_EXCEPTION(args, except) (args).SetException(except) 63 # define SET_RETURN_VALUE(args, value) (args).SetReturn(value) 64 # define GET_ARG_THIS(args) ((args).thisv()) 80 template <
bool ReturnPromise>
85 const std::string& func_name,
86 const std::string& target_name) {
87 return General(args, func_name, target_name,
"Illegal invocation");
91 const std::string&
name,
const std::string& target,
92 size_t required,
size_t given) {
93 constexpr
const char* kFormat =
94 "%zu arguments required, but only %zu present.";
96 return General(args, name, target, buffer);
100 const std::string&
name,
const std::string& target,
101 const std::string& given,
102 const std::string& required) {
103 constexpr
const char* kFormat =
"Cannot convert '%s' to '%s'.";
104 const std::string buffer =
106 return General(args, name, target, buffer);
109 static bool General(
const CallbackArguments* args,
const std::string&
name,
110 const std::string& target,
const std::string&
message) {
111 constexpr
const char* kFormat =
"Failed to execute '%s' on '%s': %s";
113 kFormat, name.c_str(), target.c_str(), message.c_str());
120 SET_RETURN_VALUE(*args, ret.
ToJsValue());
124 LocalVar<JsValue> except = value.
error();
125 SET_EXCEPTION(*args, except);
150 template <
typename Ret>
152 static bool SetReturn(
const CallbackArguments& arguments,
const Ret& ret) {
153 SET_RETURN_VALUE(arguments,
ToJsValue(ret));
159 static bool SetReturn(
const CallbackArguments& arguments,
161 if (holds_alternative<js::JsError>(ret)) {
162 LocalVar<JsValue> except = get<js::JsError>(ret).error();
163 SET_EXCEPTION(arguments, except);
169 template <
typename T>
171 static bool SetReturn(
const CallbackArguments& arguments,
173 if (holds_alternative<T>(ret)) {
174 SET_RETURN_VALUE(arguments,
ToJsValue(get<T>(ret)));
177 LocalVar<JsValue> except = get<js::JsError>(ret).error();
178 SET_EXCEPTION(arguments, except);
189 template <
typename Ret>
191 template <
typename Func,
typename... Args>
192 static bool Call(
const CallbackArguments& arguments, Func callback,
194 static_assert(!std::is_rvalue_reference<Ret>::value,
195 "Cannot return an rvalue reference.");
196 Ret ret = callback(std::forward<Args>(args)...);
202 template <
typename Func,
typename... Args>
203 static bool Call(
const CallbackArguments& arguments, Func callback,
205 callback(std::forward<Args>(args)...);
212 template <
size_t ArgIndex,
size_t ArgCount>
214 template <
typename Func,
typename... GivenArgs>
216 const std::string& target_name,
218 const CallbackArguments& arguments,
219 Func&& callback, GivenArgs&&... args) {
222 return Helper<CurType>::ConvertAndCallFunction(
223 func_name, target_name, is_member_func, arguments,
224 std::forward<Func>(callback), std::forward<GivenArgs>(args)...);
228 template <
typename CurType,
typename =
void>
230 template <
typename Func,
typename... GivenArgs>
231 static bool ConvertAndCallFunction(
const std::string& func_name,
232 const std::string& target_name,
234 const CallbackArguments& arguments,
236 GivenArgs&&... args) {
243 &arguments, func_name, target_name, arg_count,
249 LocalVar<JsValue>
source = is_member_func && ArgIndex == 0
250 ? GET_ARG_THIS(arguments)
251 : arguments[ArgIndex - is_member_func];
256 &arguments, func_name, target_name, value, type_name);
261 func_name, target_name, is_member_func, arguments,
262 std::forward<Func>(callback), std::forward<GivenArgs>(args)...,
267 template <
typename T>
268 struct Helper<const CallbackArguments&, T> {
269 static_assert(ArgIndex + 1 == ArgCount,
270 "CallbackArguments must appear last");
271 template <
typename Func,
typename... GivenArgs>
272 static bool ConvertAndCallFunction(
const std::string& func_name,
273 const std::string& target_name,
275 const CallbackArguments& arguments,
277 GivenArgs&&... args) {
279 func_name, target_name, is_member_func, arguments,
280 std::forward<Func>(callback), std::forward<GivenArgs>(args)...,
287 template <
size_t ArgCount>
289 template <
typename Func,
typename... GivenArgs>
291 const std::string& target_name,
293 const CallbackArguments& arguments,
294 Func&& callback, GivenArgs&&... args) {
297 std::forward<GivenArgs>(args)...);
308 template <
typename Func>
310 template <
typename T>
321 #if defined(USING_JSC) 323 inline void InternalCallbackDataFinalize(JSObjectRef
object) {
324 void* ptr = JSObjectGetPrivate(
object);
328 const JSClassDefinition kInternalCallbackDataDefinition = {
330 .className =
"InternalCallbackData",
331 .finalize = &InternalCallbackDataFinalize,
334 inline JSClassRef GetCallbackDataClass() {
335 static JSClassRef cls =
nullptr;
337 CHECK(cls = JSClassCreate(&kInternalCallbackDataDefinition));
350 template <
typename T,
typename Arg>
353 v8::Local<v8::ArrayBuffer> ret =
354 v8::ArrayBuffer::New(
GetIsolate(),
sizeof(T));
356 void* ptr = ret->GetContents().Data();
357 *extra_data =
new (ptr) T(std::forward<Arg>(arg));
359 DCHECK_EQ(reinterpret_cast<void*>(*extra_data), ptr);
361 reinterpret_cast<T*
>(obj)->~T();
365 #elif defined(USING_JSC) 366 *extra_data =
new T(std::forward<Arg>(arg));
371 LocalVar<JsObject> ret =
372 JSObjectMake(
GetContext(), GetCallbackDataClass(),
373 static_cast<InternalCallbackDataBase*>(*extra_data));
389 template <
typename T,
typename Info>
390 T* GetInternalData(
const Info& arguments) {
391 if (arguments.Data().IsEmpty() || !arguments.Data()->IsArrayBuffer()) {
393 nullptr,
"",
"",
"INTERNAL: Invalid function data.");
396 v8::Local<v8::ArrayBuffer> extra =
397 arguments.Data().template As<v8::ArrayBuffer>();
398 return reinterpret_cast<T*
>(extra->GetContents().Data());
400 #elif defined(USING_JSC) 401 template <
typename T>
402 T* GetInternalData(
const CallbackArguments& arguments) {
404 void* ptr =
IsObject(data) ? JSObjectGetPrivate(UnsafeJsCast<JsObject>(data))
408 nullptr,
"",
"",
"INTERNAL: Invalid function data.");
416 template <
typename Func>
419 #if defined(USING_V8) 420 static void Call(
const CallbackArguments& arguments) {
424 #elif defined(USING_JSC) 425 static JSValueRef Call(JSContextRef cx, JSObjectRef callee,
426 JSObjectRef thisv,
size_t arg_count,
427 const JSValueRef* args, JSValueRef* except) {
431 CallbackArguments arguments(args, arg_count, callee, thisv, except);
432 if (!CallRaw(arguments))
434 return arguments.ret();
439 static bool CallRaw(
const CallbackArguments& arguments) {
440 auto data = GetInternalData<InternalCallbackData<Func>>(arguments);
446 data->name, data->target, data->is_member_func, arguments,
457 template <
typename This,
typename =
void>
461 template <
typename This>
463 using type = decltype(&This::Create);
475 template <
typename This>
481 nullptr,
"constructor", type_name);
484 template <
typename This,
typename... Args>
489 auto ctor = [&](Args... args) {
490 BackingObject* backing = This::Create(std::forward<Args>(args)...);
493 return CallHelper<0,
sizeof...(Args)>::ConvertAndCallFunction(
494 "constructor", type_name,
false, arguments, std::move(ctor));
509 template <
typename This>
512 #if defined(USING_V8) 513 static void Call(
const v8::FunctionCallbackInfo<v8::Value>& arguments) {
516 const bool is_valid = !arguments.This().IsEmpty() &&
517 arguments.This()->InternalFieldCount() ==
519 CallRaw(arguments, is_valid);
521 #elif defined(USING_JSC) 522 static JSObjectRef Call(JSContextRef cx, JSObjectRef callee,
size_t arg_count,
523 const JSValueRef* args, JSValueRef* except) {
527 CallbackArguments arguments(args, arg_count, callee,
nullptr, except);
528 if (!CallRaw(arguments,
true))
530 return UnsafeJsCast<JsObject>(arguments.ret());
535 static bool CallRaw(
const CallbackArguments& arguments,
bool is_valid) {
539 nullptr,
"constructor", type_name);
556 template <
typename Func>
558 const std::string&
name,
560 bool is_member_func) {
562 LocalVar<JsValue> js_value =
570 return v8::Function::New(
GetIsolate()->GetCurrentContext(),
573 v8::ConstructorBehavior::kThrow).ToLocalChecked();
574 #elif defined(USING_JSC) 576 LocalVar<JsObject> ret =
580 const int attributes = kJSPropertyAttributeReadOnly |
581 kJSPropertyAttributeDontEnum |
582 kJSPropertyAttributeDontDelete;
584 js_value, attributes,
nullptr);
603 template <
typename Func>
605 const std::string&
name,
608 target, name, std::forward<Func>(callback),
false);
616 template <
typename Func>
618 const std::string&
name,
621 std::forward<Func>(callback),
true);
631 template <
typename Func>
633 LocalVar<JsFunction>
function =
642 template <
typename Func>
644 template <
typename T>
655 #endif // SHAKA_EMBEDDED_MAPPING_REGISTER_MEMBER_H_ static bool SetReturn(const CallbackArguments &arguments, const Ret &ret)
static bool NotEnoughArgs(const CallbackArguments *args, const std::string &name, const std::string &target, size_t required, size_t given)
ReturnVal< JsFunction > CreateStaticFunction(const std::string &target, const std::string &name, Func &&callback)
static bool SetReturn(const CallbackArguments &arguments, const ExceptionOr< void > &ret)
static ReturnVal< JsValue > ToJsValue(T &&source)
decltype(&This::Create) type
bool IsObject(Handle< JsValue > value)
bool FromJsValue(Handle< JsValue > source, T *dest)
std::string StringPrintf(const char *format,...)
bool ConstructWrapperObject(const CallbackArguments &arguments, BackingObject *that)
size_t ArgumentCount(const CallbackArguments &arguments)
InternalCallbackData(T &&arg)
static bool Call(const CallbackArguments &arguments, Func callback, Args &&... args)
ReturnVal< JsValue > ToJsValue(T &&source)
ReturnVal< JsFunction > CreateJsFunctionFromCallback(const std::string &target, const std::string &name, Func &&callback, bool is_member_func)
static bool Raw(const CallbackArguments *args, const js::JsError &value)
ReturnVal< JsValue > ToJsValue() const override
static bool IllegalInvocation(const CallbackArguments *args, const std::string &func_name, const std::string &target_name)
constexpr const char * kHiddenPropertyName
ReturnVal< JsValue > CreateInternalData(T **extra_data, Arg &&arg)
ReturnVal< JsValue > RawToJsValue(Handle< T > source)
virtual ~InternalCallbackDataBase()
typename std::remove_cv< typename std::remove_reference< T >::type >::type RawType
static constexpr const size_t kInternalFieldCount
ReturnVal< JsValue > error() const
static JsEngine * Instance()
static Promise Rejected(const js::JsError &error)
static bool ConvertAndCallFunction(const std::string &func_name, const std::string &target_name, bool is_member_func, const CallbackArguments &arguments, Func &&callback, GivenArgs &&... args)
static bool SetReturn(const CallbackArguments &arguments, const ExceptionOr< T > &ret)
static bool CreateOrThrow(const CallbackArguments &arguments)
void SetMemberRaw(Handle< JsObject > object, const std::string &name, Handle< JsValue > value)
void RegisterGlobalFunction(const std::string &name, Func &&callback)
std::decay< Func >::type callback
std::string ConvertToString(Handle< JsValue > value)
static constexpr const size_t kBufferSize
static JsError TypeError(const std::string &message)
JSContextRef GetContext()
static bool ConvertAndCallFunction(const std::string &func_name, const std::string &target_name, bool is_member_func, const CallbackArguments &arguments, Func &&callback, GivenArgs &&... args)
ReturnVal< JsString > JsStringFromUtf8(const std::string &str)
static bool Call(const CallbackArguments &arguments, Func callback, Args &&... args)
v8::Isolate * GetIsolate()
static std::string name()
static bool CannotConvert(const CallbackArguments *args, const std::string &name, const std::string &target, const std::string &given, const std::string &required)
ReturnVal< JsValue > GetMemberRaw(Handle< JsObject > object, const std::string &name, LocalVar< JsValue > *exception=nullptr)
static bool General(const CallbackArguments *args, const std::string &name, const std::string &target, const std::string &message)
void * MaybeUnwrapPointer(Handle< JsValue > value)
static bool CreateOrThrow(const CallbackArguments &arguments)
ReturnVal< JsFunction > CreateMemberFunction(const std::string &target, const std::string &name, Func &&callback)