5 #define V8TOOLKIT_BIDIRECTIONAL_ENABLED 31 virtual const char *
what() const noexcept {
return reason.c_str(); }
49 mutable bool called_from_javascript =
false;
55 isolate(context->GetIsolate()),
56 global_context(
v8::Global<
v8::
Context>(isolate, context)),
57 global_js_object(
v8::Global<
v8::Object>(isolate, object)),
90 return object->get_javascript_object();
119 #ifndef V8_CLASS_WRAPPER_HAS_BIDIRECTIONAL_SUPPORT 120 #error bidirectional.h must be included before v8_class_wrapper.h 158 class Deleter = std::default_delete<Base>>
162 template<
class Base,
class... ConstructorArgs,
class FactoryBase,
class Deleter>
163 class Factory<Base,
TypeList<ConstructorArgs...>, FactoryBase, Deleter> :
public virtual FactoryBase {
177 virtual Base * operator()(ConstructorArgs&&... constructor_args)
const = 0;
179 Base *
create(ConstructorArgs&&... constructor_args)
const {
180 return this->operator()(std::forward<ConstructorArgs>(constructor_args)...);
186 template <
class U = Base>
187 std::unique_ptr<U>
get_unique(ConstructorArgs&&... args)
const {
190 return std::unique_ptr<U>((*this)(std::forward<ConstructorArgs>(args)...));
196 template<
class U,
class...
Args>
199 auto result = this->operator()(std::forward<Args>(args)...);
200 if (dynamic_cast<U*>(result)) {
201 return static_cast<U*
>(result);
217 class FixedParamsTypeList,
218 class ExternalTypeList,
220 class Deleter = std::default_delete<Child> >
225 template<
class Base,
class Child,
class... ExternalConstructorParams,
class... FixedParams,
class FactoryBase,
class Deleter>
229 TypeList<ExternalConstructorParams...>,
231 Deleter> :
public virtual FactoryBase {
234 using TupleType = std::tuple<FixedParams...>;
235 TupleType fixed_param_tuple;
241 fixed_param_tuple(fixed_param_values...) {}
252 template<std::size_t... Is>
253 Base *
call_operator_helper(ExternalConstructorParams &&... constructor_args, std::index_sequence<Is...>)
const {
256 return new Child(std::forward<FixedParams>(std::get<Is>(const_cast<TupleType &>(fixed_param_tuple)))...,
257 std::forward<ExternalConstructorParams>(constructor_args)...);
260 virtual Base *
operator()(ExternalConstructorParams &&... constructor_args)
const override {
261 return call_operator_helper(std::forward<ExternalConstructorParams>(constructor_args)...,
262 std::index_sequence_for<FixedParams...>());
284 class JSWrapperClass,
289 class Deleter = std::default_delete<JSWrapperClass>>
296 class JSWrapperClass,
298 class... InternalConstructorParams,
299 class... ExternalConstructorParams,
306 TypeList<InternalConstructorParams...>,
307 TypeList<ExternalConstructorParams...>,
332 using TupleType = std::tuple<InternalConstructorParams...>;
341 template<
int starting_info_index, std::size_t... Is>
344 auto isolate = info.GetIsolate();
345 auto context = isolate->GetCurrentContext();
348 constexpr std::size_t parameter_count = starting_info_index + 2 +
sizeof...(InternalConstructorParams);
349 if (info.Length() != parameter_count) {
350 throw InvalidCallException(fmt::format(
"Wrong number of parameters to create new factory - needs {}, got {}", parameter_count, info.Length()));
353 int i = starting_info_index + 2;
354 std::vector<std::unique_ptr<v8toolkit::StuffBase>> stuff;
358 std::unique_ptr<ThisFactoryType>,
360 decltype(info[starting_info_index + 0]->ToObject()),
362 InternalConstructorParams...>
366 decltype(info[starting_info_index + 0]->ToObject()),
367 v8::Local<v8::Function>,
368 InternalConstructorParams...>,
371 info[starting_info_index + 0]->ToObject(),
378 template<std::size_t... Is>
380 ExternalConstructorParams&&... constructor_args,
381 std::index_sequence<Is...>)
const {
383 return std::make_unique<JSWrapperClass>(this->global_context.Get(isolate),
385 this->js_base_constructor_function.Get(isolate),
388 std::forward<InternalConstructorParams>(std::get<Is>(
const_cast<TupleType &
>(this->internal_param_tuple)))...,
389 std::forward<ExternalConstructorParams>(constructor_args)...);
400 InternalConstructorParams&&... internal_constructor_values) :
402 isolate(context->GetIsolate()),
403 global_context(
v8::Global<
v8::
Context>(isolate, context)),
407 js_new_object_constructor_function(
v8::Global<
v8::Function>(isolate, js_new_object_constructor_function)),
408 js_prototype(
v8::Global<
v8::Object>(isolate, prototype)),
409 internal_param_tuple(internal_constructor_values...)
420 auto new_js_object = js_base_constructor_function.Get(isolate)->GetFunction()->NewInstance();
421 (void) this->js_prototype.Get(isolate)->SetPrototype(context, new_js_object->GetPrototype());
425 this->make_jswrapper_object =
426 [
this](ExternalConstructorParams&&... external_constructor_values)
mutable ->JSWrapperClass * {
429 auto context = this->global_context.Get(this->isolate);
432 v8::Local<v8::Object> new_js_object = this->js_base_constructor_function.Get(isolate)->GetFunction()->NewInstance();
434 (void)new_js_object->SetPrototype(context, this->js_prototype.Get(isolate));
437 auto js_wrapper_class_cpp_object =
438 call_operator_helper(new_js_object,
439 std::forward<ExternalConstructorParams>(external_constructor_values)...,
440 std::index_sequence_for<InternalConstructorParams...>());
449 wrapper.template initialize_new_js_object(isolate, new_js_object, js_wrapper_class_cpp_object.get(), *wrapper.destructor_behavior_leave_alone);
453 this->js_new_object_constructor_function.Get(isolate),
455 TypeList<ExternalConstructorParams...>(),
456 std::forward<ExternalConstructorParams>(external_constructor_values)...);
457 return js_wrapper_class_cpp_object.release();
471 virtual Base *
operator()(ExternalConstructorParams&&... constructor_parameters)
const override {
472 return this->make_jswrapper_object(std::forward<ExternalConstructorParams>(constructor_parameters)...);
476 template<
int starting_info_index>
478 return _create_factory_from_javascript<starting_info_index>(info, std::index_sequence_for<InternalConstructorParams...>());
484 wrapper.add_method(
"create", &ThisFactoryType::operator());
493 #define JS_ACCESS_CORE_DEBUG false 507 #define JS_ACCESS_CORE(ReturnType, name, ...) \ 508 bool call_native = this->called_from_javascript; \ 515 this->called_from_javascript = false; \ 517 if(JS_ACCESS_CORE_DEBUG) printf("Calling native version of %s\n", #name); \ 519 return this->BASE_TYPE::name( __VA_ARGS__ ); \ 521 if(JS_ACCESS_CORE_DEBUG) printf("IN JS_ACCESS_CORE for %s, not calling native code\n", #name); \ 524 v8toolkit::CastToNative<std::remove_reference<ReturnType>::type> cast_to_native; \ 525 GLOBAL_CONTEXT_SCOPED_RUN(isolate, global_context); \ 526 auto context = global_context.Get(isolate); \ 527 auto js_object = global_js_object.Get(isolate); \ 528 v8::Local<v8::Function> js_function; \ 529 v8::TryCatch tc(isolate); \ 531 js_function = v8toolkit::get_key_as<v8::Function>(context, js_object, #name); \ 532 } catch (...) {assert(((void)"method probably not added to wrapped parent type", false) == true);} \ 533 this->called_from_javascript = true; \ 534 auto result = v8toolkit::call_javascript_function_with_vars(context, js_function, js_object, typelist, ##__VA_ARGS__); \ 535 this->called_from_javascript = false; \ 536 return cast_to_native(isolate, result); 540 #define JS_ACCESS(return_type, name)\ 541 virtual return_type name() override {\ 542 v8toolkit::TypeList<> typelist; \ 543 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name)\ 546 #define JS_ACCESS_0(return_type, name)\ 547 virtual return_type name() override {\ 548 v8toolkit::TypeList<> typelist; \ 549 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name)\ 552 #define JS_ACCESS_1(return_type, name, t1)\ 553 virtual return_type name(t1 p1) override {\ 554 v8toolkit::TypeList<t1> typelist; \ 555 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1)\ 558 #define JS_ACCESS_2(return_type, name, t1, t2) \ 559 virtual return_type name(t1 p1, t2 p2) override { \ 560 v8toolkit::TypeList<t1, t2> typelist; \ 561 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2) \ 564 #define JS_ACCESS_3(return_type, name, t1, t2, t3)\ 565 virtual return_type name(t1 p1, t2 p2, t3 p3) override { \ 566 v8toolkit::TypeList<t1, t2, t3> typelist; \ 567 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3) \ 570 #define JS_ACCESS_4(return_type, name, t1, t2, t3, t4)\ 571 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4) override {\ 572 v8toolkit::TypeList<t1, t2, t3, t4> typelist; \ 573 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4)\ 576 #define JS_ACCESS_5(return_type, name, t1, t2, t3, t4, t5)\ 577 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5) override {\ 578 v8toolkit::TypeList<t1, t2, t3, t4, t5> typelist; \ 579 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4, p5)\ 582 #define JS_ACCESS_6(return_type, name, t1, t2, t3, t4, t5, t6)\ 583 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6) override {\ 584 v8toolkit::TypeList<t1, t2, t3, t4, t5, t6> typelist; \ 585 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4, p5, p6)\ 588 #define JS_ACCESS_7(return_type, name, t1, t2, t3, t4, t5, t6, t7)\ 589 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7) override {\ 590 v8toolkit::TypeList<t1, t2, t3, t4, t5, t6, t7> typelist; \ 591 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4, p5, p6, p7)\ 594 #define JS_ACCESS_8(return_type, name, t1, t2, t3, t4, t5, t6, t7, t8)\ 595 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8) override {\ 596 v8toolkit::TypeList<t1, t2, t3, t4, t5, t6, t7, t8> typelist; \ 597 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4, p5, p6, p7, p8)\ 600 #define JS_ACCESS_9(return_type, name, t1, t2, t3, t4, t5, t6, t7, t8, t9)\ 601 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9) override {\ 602 v8toolkit::TypeList<t1, t2, t3, t4, t5, t6, t7, t8, t9> typelist; \ 603 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4, p5, p6, p7, p8, p9)\ 606 #define JS_ACCESS_CONST(return_type, name)\ 607 virtual return_type name() const override {\ 608 v8toolkit::TypeList<> typelist; \ 609 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name)\ 612 #define JS_ACCESS_0_CONST(return_type, name)\ 613 virtual return_type name() const override {\ 614 v8toolkit::TypeList<> typelist; \ 615 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name)\ 619 #define JS_ACCESS_1_CONST(return_type, name, t1)\ 620 virtual return_type name(t1 p1) const override {\ 621 v8toolkit::TypeList<t1> typelist; \ 622 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1)\ 625 #define JS_ACCESS_2_CONST(return_type, name, t1, t2)\ 626 virtual return_type name(t1 p1, t2 p2) const override {\ 627 v8toolkit::TypeList<t1, t2> typelist; \ 628 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2)\ 631 #define JS_ACCESS_3_CONST(return_type, name, t1, t2, t3)\ 632 virtual return_type name(t1 p1, t2 p2, t3 p3) const override {\ 633 v8toolkit::TypeList<t1, t2, t3> typelist; \ 634 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3)\ 637 #define JS_ACCESS_4_CONST(return_type, name, t1, t2, t3, t4)\ 638 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4) const override {\ 639 v8toolkit::TypeList<t1, t2, t3, t4> typelist; \ 640 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4)\ 643 #define JS_ACCESS_5_CONST(return_type, name, t1, t2, t3, t4, t5)\ 644 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5) const override {\ 645 v8toolkit::TypeList<t1, t2, t3, t4, t5> typelist; \ 646 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4, p5)\ 649 #define JS_ACCESS_6_CONST(return_type, name, t1, t2, t3, t4, t5, t6)\ 650 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6) const override {\ 651 v8toolkit::TypeList<t1, t2, t3, t4, t5, t6> typelist; \ 652 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4, p5, p6)\ 655 #define JS_ACCESS_7_CONST(return_type, name, t1, t2, t3, t4, t5, t6, t7)\ 656 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7) const override {\ 657 v8toolkit::TypeList<t1, t2, t3, t4, t5, t6, t7> typelist; \ 658 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4, p5, p6, p7)\ 661 #define JS_ACCESS_8_CONST(return_type, name, t1, t2, t3, t4, t5, t6, t7, t8)\ 662 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8) const override {\ 663 v8toolkit::TypeList<t1, t2, t3, t4, t5, t6, t7, t8> typelist; \ 664 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4, p5, p6, p7, p8)\ 667 #define JS_ACCESS_9_CONST(return_type, name, t1, t2, t3, t4, t5, t6, t7, t8, t9)\ 668 virtual return_type name(t1 p1, t2 p2, t3 p3, t4 p4, t5 p5, t6 p6, t7 p7, t8 p8, t9 p9) const override {\ 669 v8toolkit::TypeList<t1, t2, t3, t4, t5, t6, t7, t8, t9> typelist; \ 670 JS_ACCESS_CORE(V8TOOLKIT_MACRO_TYPE(return_type), name, p1, p2, p3, p4, p5, p6, p7, p8, p9)\
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)