diff --git a/include/client/new/client.h b/include/client/new/client.h index 604b83e..ec88e33 100644 --- a/include/client/new/client.h +++ b/include/client/new/client.h @@ -86,6 +86,8 @@ inline void freeCallback(client::EventListener* e) EscapedListeners::free(e); } +template +class Closure; template class Closure; template @@ -98,30 +100,22 @@ class Closure typedef R(func_t)(Args...); template - using _Convertible = typename cheerp::utility::enable_if::value>::type; - + static constexpr bool is_convertible = cheerp::utility::is_convertible<_Tp, func_t*>::value; template - using _NConvertible = typename cheerp::utility::enable_if::value>::type; + static constexpr bool has_trivial_destructor = __is_trivially_destructible(typename cheerp::utility::remove_reference<_Tp>::type); - template - using _en_if = typename cheerp::utility::enable_if<_Cond::value>::type; - template - using _en_if_not = typename cheerp::utility::enable_if::type; - - template - struct _bool_const - { - static constexpr bool value = V; - }; - template struct _must_destroy - : public _bool_const::type)> {}; template - static void do_delete(void* o) - { + static void do_delete(void* o) { T* t = reinterpret_cast(o); delete t; } + template + static void do_delete_wasm(void* o) + { + T* t = reinterpret_cast(addrspace_cast<__wasm void*>(o)); + delete t; + } struct DeleterHelper { void(*deleter)(void*); @@ -136,29 +130,31 @@ class Closure { } template - Closure(F&& f, _NConvertible* = 0, _en_if<_must_destroy>* = 0) + Closure(F&& f) { using FF = typename cheerp::utility::remove_cv::type>::type; - FF* newf = new FF(::cheerp::utility::forward(f)); - inner = __builtin_cheerp_create_closure(&InvokeHelper::template invoke, newf); - deleter = &do_delete; - obj = newf; - } - template - Closure(F&& f, _NConvertible* = 0, _en_if_not<_must_destroy>* = 0) - { - using FF = typename cheerp::utility::remove_reference::type; - FF* newf = new FF(::cheerp::utility::forward(f)); - inner = __builtin_cheerp_create_closure(&InvokeHelper::template invoke, newf); - deleter = nullptr; - obj = newf; - } - template - Closure(F f, _Convertible* = 0) - { - inner = __builtin_cheerp_make_complete_object((func_t*)f); - deleter = nullptr; - obj = nullptr; + constexpr bool is_wasm = cheerp::utility::is_same::value; + if constexpr (is_convertible) { + inner = __builtin_cheerp_make_complete_object((func_t*)f); + obj = nullptr; + } else { + FF* newf = new FF(::cheerp::utility::forward(f)); + inner = __builtin_cheerp_create_closure(&cheerp::InvokeHelper::template invoke, newf); + if constexpr (is_wasm) { + obj = addrspace_cast(reinterpret_cast<__wasm void*>(newf)); + } else { + obj = reinterpret_cast(newf); + } + } + if constexpr (!has_trivial_destructor) { + if constexpr (is_wasm) { + deleter = &do_delete_wasm; + } else { + deleter = &do_delete; + } + } else { + deleter = nullptr; + } } Closure(R(*f)(Args...)) { @@ -224,8 +220,35 @@ class Closure template struct ClosureHelper; // undefined template struct ClosureHelperBase; +template +using ClassMethodType = R(C::*)(Args...); +template +using ClassMethodTypeConst = R(C::*)(Args...) const; +template +using ClassMethodTypeConstWasm = R(C::*)(Args...) const [[cheerp::wasm_as]]; +template +using ClassMethodTypeWasm = R(C::*)(Args...) [[cheerp::wasm_as]]; + +template +struct ClosureHelper> +{ + typedef R (func_type)(Args...); + static Closure make_closure(T&& func) + { + return Closure(::cheerp::utility::forward(func)); + } +}; +template +struct ClosureHelper> +{ + typedef R (func_type)(Args...); + static Closure make_closure(T&& func) + { + return Closure(::cheerp::utility::forward(func)); + } +}; template -struct ClosureHelper +struct ClosureHelper> { typedef R (func_type)(Args...); static Closure make_closure(T&& func) @@ -234,7 +257,7 @@ struct ClosureHelper } }; template -struct ClosureHelper +struct ClosureHelper> { typedef R (func_type)(Args...); static Closure make_closure(T&& func) diff --git a/tests/unit/virtual/rtti.cpp b/tests/unit/virtual/rtti.cpp index 05b789e..801d7c0 100644 --- a/tests/unit/virtual/rtti.cpp +++ b/tests/unit/virtual/rtti.cpp @@ -85,12 +85,20 @@ class F: public A, public E float f2; }; +#ifdef __ASMJS__ +const char* expected_typeid1 = "PU4wasm1I"; +const char* expected_typeid2 = "PU4wasmd"; +#else +const char* expected_typeid1 = "PU2js1I"; +const char* expected_typeid2 = "PU2jsd"; +#endif + void testTypeidName() { { I* a = new A(); I* t = dynamic_cast(a); const char *name = typeid(t).name(); - assertEqual(name, "P1I", "typeid().name() support 1/N"); + assertEqual(name, expected_typeid1, "typeid().name() support 1/N"); } { @@ -102,7 +110,7 @@ void testTypeidName() { { double *doubleptr = nullptr; const std::type_info &ti = typeid(doubleptr); - assertEqual(ti.name(), "Pd", "typeid().name() support 3/N"); + assertEqual(ti.name(), expected_typeid2, "typeid().name() support 3/N"); } // Dereferencing a null pointer: okay for a non-polymorphic expression