diff --git a/system/include/emscripten/bind.h b/system/include/emscripten/bind.h index 9bceabd53481e..a787a92fdd4f2 100644 --- a/system/include/emscripten/bind.h +++ b/system/include/emscripten/bind.h @@ -283,181 +283,6 @@ struct InitFunc { } // end namespace internal -//////////////////////////////////////////////////////////////////////////////// -// POLICIES -//////////////////////////////////////////////////////////////////////////////// - -template -struct arg { - static constexpr int index = Index + 1; -}; - -struct ret_val { - static constexpr int index = 0; -}; - -/* -template -struct allow_raw_pointer { - template - struct Transform { - typedef typename std::conditional< - Index == Slot::index, - internal::AllowedRawPointer::type>, - InputType - >::type type; - }; -}; -*/ - -// allow all raw pointers -struct allow_raw_pointers { - template - struct Transform { - // Use decay to handle references to pointers e.g.(T*&)->(T*). - typedef typename std::decay::type DecayedType; - typedef typename std::conditional< - std::is_pointer::value, - internal::AllowedRawPointer::type>, - InputType - >::type type; - }; -}; - -// this is temporary until arg policies are reworked -template -struct allow_raw_pointer : public allow_raw_pointers { -}; - -struct async { - template - struct Transform { - typedef InputType type; - }; -}; - -struct pure_virtual { - template - struct Transform { - typedef InputType type; - }; -}; - -template -struct nonnull { - static_assert(std::is_same::value, "Only nonnull return values are currently supported."); - template - struct Transform { - typedef InputType type; - }; -}; - -namespace return_value_policy { - -struct take_ownership : public allow_raw_pointers {}; -struct reference : public allow_raw_pointers {}; - -} // end namespace return_value_policy - -namespace internal { - -#if __cplusplus >= 201703L -template using conjunction = std::conjunction; -template using disjunction = std::disjunction; -#else -// Helper available in C++14. -template -using conditional_t = typename std::conditional<_Test, _T1, _T2>::type; - -template struct conjunction : std::true_type {}; -template struct conjunction : B1 {}; -template -struct conjunction - : conditional_t, B1> {}; - -template struct disjunction : std::false_type {}; -template struct disjunction : B1 {}; -template -struct disjunction - : conditional_t, B1> {}; -#endif - -template -struct isPolicy; - -template -struct isPolicy { - static constexpr bool value = true; -}; - -template -struct isPolicy { - static constexpr bool value = true; -}; - -template -struct isPolicy { - static constexpr bool value = true; -}; - -template -struct isPolicy, Rest...> { - static constexpr bool value = true; -}; - -template -struct isPolicy { - static constexpr bool value = true; -}; - -template -struct isPolicy { - static constexpr bool value = true; -}; - -template -struct isPolicy, Rest...> { - static constexpr bool value = true; -}; - -template -struct isPolicy { - static constexpr bool value = isPolicy::value; -}; - -template<> -struct isPolicy<> { - static constexpr bool value = false; -}; - -template -struct GetReturnValuePolicy { - using tag = rvp::default_tag; -}; - -template -struct GetReturnValuePolicy { - using tag = rvp::take_ownership; -}; - -template -struct GetReturnValuePolicy { - using tag = rvp::reference; -}; - -template -struct GetReturnValuePolicy { - using tag = GetReturnValuePolicy::tag; -}; - -template -using isAsync = disjunction...>; - -template -using isNonnullReturn = disjunction, Policies>...>; - -} - //////////////////////////////////////////////////////////////////////////////// // select_overload and select_const //////////////////////////////////////////////////////////////////////////////// diff --git a/system/include/emscripten/val.h b/system/include/emscripten/val.h index a57c11a944bc5..32c1c4c214f4d 100644 --- a/system/include/emscripten/val.h +++ b/system/include/emscripten/val.h @@ -345,7 +345,7 @@ class EMBIND_VISIBILITY_DEFAULT val { explicit val(T&& value, Policies...) { using namespace internal; - new (this) val(internalCall, val>(nullptr, nullptr, std::forward(value))); + new (this) val(internalCallWithPolicy, val>(nullptr, nullptr, std::forward(value))); } val() : val(EM_VAL(internal::_EMVAL_UNDEFINED)) {} @@ -492,28 +492,28 @@ class EMBIND_VISIBILITY_DEFAULT val { val new_(Args&&... args) const { using namespace internal; - return internalCall, val>(as_handle(), nullptr, std::forward(args)...); + return internalCall(as_handle(), nullptr, std::forward(args)...); } template val operator()(Args&&... args) const { using namespace internal; - return internalCall, val>(as_handle(), nullptr, std::forward(args)...); + return internalCall(as_handle(), nullptr, std::forward(args)...); } template ReturnValue call(const char* name, Args&&... args) const { using namespace internal; - return internalCall, ReturnValue>(as_handle(), name, std::forward(args)...); + return internalCall(as_handle(), name, std::forward(args)...); } template T as(Policies...) const { using namespace internal; - return internalCall, T>(as_handle(), nullptr, *this); + return internalCallWithPolicy, T>(as_handle(), nullptr, *this); } // Prefer calling val::typeOf() over val::typeof(), since this form works in both C++11 and GNU++11 build modes. "typeof" is a reserved word in GNU++11 extensions. @@ -573,8 +573,27 @@ class EMBIND_VISIBILITY_DEFAULT val { template friend val internal::wrapped_extend(const std::string& , const val& ); - template + template static Ret internalCall(EM_VAL handle, const char *methodName, Args&&... args) { + using namespace internal; +#if __cplusplus >= 201703L + using Policy = WithPolicies>; + auto filteredArgs = Filter(args...); + return std::apply( + [&](auto&&... filteredArgs) { + return internalCallWithPolicy(handle, methodName, std::forward(filteredArgs)...); + }, + filteredArgs + ); +#else + // When std::apply is not available allow pointers by default. std::apply + // could be polyfilled, but it requires a lot of code. + return internalCallWithPolicy, Ret>(handle, methodName, std::forward(args)...); +#endif + } + + template + static Ret internalCallWithPolicy(EM_VAL handle, const char *methodName, Args&&... args) { static_assert(!std::is_lvalue_reference::value, "Cannot create a lvalue reference out of a JS value."); diff --git a/system/include/emscripten/wire.h b/system/include/emscripten/wire.h index 33cf72eafbbbe..aa993e806a5f1 100644 --- a/system/include/emscripten/wire.h +++ b/system/include/emscripten/wire.h @@ -265,6 +265,9 @@ struct WithPolicies { }; }; +template +struct WithPolicies> : WithPolicies {}; + // BindingType // The second typename is an unused stub so it's possible to @@ -492,6 +495,214 @@ struct BindingType> { } }; +} + +//////////////////////////////////////////////////////////////////////////////// +// POLICIES +//////////////////////////////////////////////////////////////////////////////// + +template +struct arg { + static constexpr int index = Index + 1; +}; + +struct ret_val { + static constexpr int index = 0; +}; + +/* +template +struct allow_raw_pointer { + template + struct Transform { + typedef typename std::conditional< + Index == Slot::index, + internal::AllowedRawPointer::type>, + InputType + >::type type; + }; +}; +*/ + +// allow all raw pointers +struct allow_raw_pointers { + template + struct Transform { + // Use decay to handle references to pointers e.g.(T*&)->(T*). + typedef typename std::decay::type DecayedType; + typedef typename std::conditional< + std::is_pointer::value, + internal::AllowedRawPointer::type>, + InputType + >::type type; + }; +}; + +// this is temporary until arg policies are reworked +template +struct allow_raw_pointer : public allow_raw_pointers { +}; + +struct async { + template + struct Transform { + typedef InputType type; + }; +}; + +struct pure_virtual { + template + struct Transform { + typedef InputType type; + }; +}; + +template +struct nonnull { + static_assert(std::is_same::value, "Only nonnull return values are currently supported."); + template + struct Transform { + typedef InputType type; + }; +}; + +namespace return_value_policy { + +struct take_ownership : public allow_raw_pointers {}; +struct reference : public allow_raw_pointers {}; + +} // end namespace return_value_policy + +namespace internal { + +#if __cplusplus >= 201703L +template using conjunction = std::conjunction; +template using disjunction = std::disjunction; +#else +// Helper available in C++14. +template +using conditional_t = typename std::conditional<_Test, _T1, _T2>::type; + +template struct conjunction : std::true_type {}; +template struct conjunction : B1 {}; +template +struct conjunction + : conditional_t, B1> {}; + +template struct disjunction : std::false_type {}; +template struct disjunction : B1 {}; +template +struct disjunction + : conditional_t, B1> {}; +#endif + +template +struct isPolicy; + +template +struct isPolicy { + static constexpr bool value = true; +}; + +template +struct isPolicy { + static constexpr bool value = true; +}; + +template +struct isPolicy { + static constexpr bool value = true; +}; + +template +struct isPolicy, Rest...> { + static constexpr bool value = true; +}; + +template +struct isPolicy { + static constexpr bool value = true; +}; + +template +struct isPolicy { + static constexpr bool value = true; +}; + +template +struct isPolicy, Rest...> { + static constexpr bool value = true; +}; + +template +struct isPolicy { + static constexpr bool value = isPolicy::value; +}; + +template<> +struct isPolicy<> { + static constexpr bool value = false; +}; + +template +struct isNotPolicy { + static constexpr bool value = !isPolicy::value; +}; + +template +struct GetReturnValuePolicy { + using tag = rvp::default_tag; +}; + +template +struct GetReturnValuePolicy { + using tag = rvp::take_ownership; +}; + +template +struct GetReturnValuePolicy { + using tag = rvp::reference; +}; + +template +struct GetReturnValuePolicy { + using tag = GetReturnValuePolicy::tag; +}; + +template +using isAsync = disjunction...>; + +template +using isNonnullReturn = disjunction, Policies>...>; + +// Build a tuple type that contains all the types where the predicate is true. +// e.g. FilterTypes would return std::tuple. +template