Employ some variadic macros to make some of the C++ -> JS function calling code nicer.
Template-ize CallFunctionVoid. Changes CallFunction parameter order to make template parameter deduction with variadic parameters work nicely. Reviewed By: Itms, wraitii, Yves Differential Revision: https://code.wildfiregames.com/D77 This was SVN commit r19183.
This commit is contained in:
parent
fd5bd8e301
commit
6ae2db53db
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2016 Wildfire Games.
|
||||
/* Copyright (C) 2017 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -347,7 +347,7 @@ InReaction CGUIManager::HandleEvent(const SDL_Event_* ev)
|
||||
JSContext* cx = top()->GetScriptInterface()->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue global(cx, top()->GetGlobalObject());
|
||||
if (top()->GetScriptInterface()->CallFunction(global, "handleInputBeforeGui", *ev, top()->FindObjectUnderMouse(), handled))
|
||||
if (top()->GetScriptInterface()->CallFunction(global, "handleInputBeforeGui", handled, *ev, top()->FindObjectUnderMouse()))
|
||||
if (handled)
|
||||
return IN_HANDLED;
|
||||
}
|
||||
@ -366,7 +366,7 @@ InReaction CGUIManager::HandleEvent(const SDL_Event_* ev)
|
||||
JS::RootedValue global(cx, top()->GetGlobalObject());
|
||||
|
||||
PROFILE("handleInputAfterGui");
|
||||
if (top()->GetScriptInterface()->CallFunction(global, "handleInputAfterGui", *ev, handled))
|
||||
if (top()->GetScriptInterface()->CallFunction(global, "handleInputAfterGui", handled, *ev))
|
||||
if (handled)
|
||||
return IN_HANDLED;
|
||||
}
|
||||
|
@ -30,10 +30,6 @@ template <typename T> struct MaybeRef;
|
||||
#define NUMBERED_LIST_TAIL_MAYBE_REF(z, i, data) , typename MaybeRef<data##i>::Type
|
||||
#define NUMBERED_LIST_BALANCED(z, i, data) BOOST_PP_COMMA_IF(i) data##i
|
||||
#define NUMBERED_LIST_BALANCED_MAYBE_REF(z, i, data) BOOST_PP_COMMA_IF(i) typename MaybeRef<data##i>::Type
|
||||
// Some other things
|
||||
#define TYPED_ARGS(z, i, data) , T##i a##i
|
||||
#define TYPED_ARGS_MAYBE_REF(z, i, data) , typename MaybeRef<T##i>::Type a##i
|
||||
#define TYPED_ARGS_CONST_REF(z, i, data) , const T##i& a##i
|
||||
|
||||
// TODO: We allow optional parameters when the C++ type can be converted from JS::UndefinedValue.
|
||||
// FromJSVal is expected to either set a##i or return false (otherwise we could get undefined
|
||||
@ -54,23 +50,17 @@ template <typename T> struct MaybeRef;
|
||||
|
||||
// List-generating macros, named roughly after their first list item
|
||||
#define TYPENAME_T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, typename T) // "typename T0, typename T1, "
|
||||
#define TYPENAME_T0_TAIL(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL, typename T) // ", typename T0, typename T1"
|
||||
#define T0(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_BALANCED, T) // "T0, T1"
|
||||
#define T0_MAYBE_REF(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_BALANCED_MAYBE_REF, T) // "const T0&, T1"
|
||||
#define T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, T) // "T0, T1, "
|
||||
#define T0_TAIL(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL, T) // ", T0, T1"
|
||||
#define T0_TAIL_MAYBE_REF(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL_MAYBE_REF, T) // ", const T0&, T1"
|
||||
#define T0_A0(z, i) BOOST_PP_REPEAT_##z (i, TYPED_ARGS, ~) // ",T0 a0, T1 a1"
|
||||
#define T0_A0_MAYBE_REF(z, i) BOOST_PP_REPEAT_##z (i, TYPED_ARGS_MAYBE_REF, ~) // ",const T0& a0, T1 a1"
|
||||
#define T0_A0_TAIL_CONST_REF(z, i) BOOST_PP_REPEAT_##z (i, TYPED_ARGS_CONST_REF, ~) // ", const T0& a0, const T1& a1"
|
||||
#define A0(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_BALANCED, a) // "a0, a1"
|
||||
#define A0_TAIL(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL, a) // ", a0, a1"
|
||||
|
||||
// Define RegisterFunction<TR, T0..., f>
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R, TYPENAME_T0_HEAD(z,i) R (*fptr) ( ScriptInterface::CxPrivate* T0_TAIL_MAYBE_REF(z,i) )> \
|
||||
void RegisterFunction(const char* name) { \
|
||||
Register(name, call<R, T0_HEAD(z,i) fptr>, nargs<0 T0_TAIL(z,i)>()); \
|
||||
Register(name, call<R T0_TAIL(z,i), fptr>, nargs<T0(z,i)>()); \
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
@ -98,33 +88,24 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
// Argument-number counter
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <int dummy TYPENAME_T0_TAIL(z,i)> /* add a dummy parameter so we still compile with 0 template args */ \
|
||||
static size_t nargs() { return i; }
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
template<typename... Ts>
|
||||
static size_t nargs() { return sizeof...(Ts); }
|
||||
|
||||
// Call the named property on the given object
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool CallFunction(JS::HandleValue val, const char* name T0_A0_TAIL_CONST_REF(z,i), R& ret) const;
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
template<typename R, typename... Ts>
|
||||
bool CallFunction(JS::HandleValue val, const char* name, R& ret, const Ts&... params) const;
|
||||
|
||||
// Implicit conversion from JS::Rooted<R>* to JS::MutableHandle<R> does not work with template argument deduction
|
||||
// (only exact type matches allowed). We need this overload to allow passing Rooted<R>* using the & operator
|
||||
// (as people would expect it to work based on the SpiderMonkey rooting guide).
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool CallFunction(JS::HandleValue val, const char* name T0_A0_TAIL_CONST_REF(z,i), JS::Rooted<R>* ret) const;
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
template<typename R, typename... Ts>
|
||||
bool CallFunction(JS::HandleValue val, const char* name, JS::Rooted<R>* ret, const Ts&... params) const;
|
||||
|
||||
// This overload is for the case when a JS::MutableHandle<R> type gets passed into CallFunction directly and
|
||||
// without requiring implicit conversion.
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool CallFunction(JS::HandleValue val, const char* name T0_A0_TAIL_CONST_REF(z,i), JS::MutableHandle<R> ret) const;
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
template<typename R, typename... Ts>
|
||||
bool CallFunction(JS::HandleValue val, const char* name, JS::MutableHandle<R> ret, const Ts&... params) const;
|
||||
|
||||
// Call the named property on the given object, with void return type
|
||||
template<typename... Ts> \
|
||||
bool CallFunctionVoid(JS::HandleValue val, const char* name, const Ts&... params) const;
|
||||
|
@ -57,10 +57,8 @@ PASS_BY_VALUE_IN_NATIVE_WRAPPER(double)
|
||||
// remove them from here and check if this causes error C2244 when compiling.
|
||||
#undef NUMBERED_LIST_TAIL_MAYBE_REF
|
||||
#undef NUMBERED_LIST_BALANCED_MAYBE_REF
|
||||
#undef TYPED_ARGS_MAYBE_REF
|
||||
#define NUMBERED_LIST_TAIL_MAYBE_REF(z, i, data) , typename ScriptInterface::MaybeRef<data##i>::Type
|
||||
#define NUMBERED_LIST_BALANCED_MAYBE_REF(z, i, data) BOOST_PP_COMMA_IF(i) typename ScriptInterface::MaybeRef<data##i>::Type
|
||||
#define TYPED_ARGS_MAYBE_REF(z, i, data) , typename ScriptInterface::MaybeRef<T##i>::Type a##i
|
||||
|
||||
// (NativeWrapperDecls.h set up a lot of the macros we use here)
|
||||
|
||||
@ -69,52 +67,46 @@ PASS_BY_VALUE_IN_NATIVE_WRAPPER(double)
|
||||
|
||||
// Templated on the return type so void can be handled separately
|
||||
template <typename R>
|
||||
struct ScriptInterface_NativeWrapper {
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<TYPENAME_T0_HEAD(z,i) typename F> \
|
||||
static void call(JSContext* cx, JS::MutableHandleValue rval, F fptr T0_A0_MAYBE_REF(z,i)) { \
|
||||
ScriptInterface::AssignOrToJSValUnrooted<R>(cx, rval, fptr(ScriptInterface::GetScriptInterfaceAndCBData(cx) A0_TAIL(z,i))); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
struct ScriptInterface_NativeWrapper
|
||||
{
|
||||
template<typename F, typename... Ts>
|
||||
static void call(JSContext* cx, JS::MutableHandleValue rval, F fptr, Ts... params)
|
||||
{
|
||||
ScriptInterface::AssignOrToJSValUnrooted<R>(cx, rval, fptr(ScriptInterface::GetScriptInterfaceAndCBData(cx), params...));
|
||||
}
|
||||
};
|
||||
|
||||
// Overloaded to ignore the return value from void functions
|
||||
template <>
|
||||
struct ScriptInterface_NativeWrapper<void> {
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<TYPENAME_T0_HEAD(z,i) typename F> \
|
||||
static void call(JSContext* cx, JS::MutableHandleValue /*rval*/, F fptr T0_A0_MAYBE_REF(z,i)) { \
|
||||
fptr(ScriptInterface::GetScriptInterfaceAndCBData(cx) A0_TAIL(z,i)); \
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
struct ScriptInterface_NativeWrapper<void>
|
||||
{
|
||||
template<typename F, typename... Ts>
|
||||
static void call(JSContext* cx, JS::MutableHandleValue UNUSED(rval), F fptr, Ts... params)
|
||||
{
|
||||
fptr(ScriptInterface::GetScriptInterfaceAndCBData(cx), params...);
|
||||
}
|
||||
};
|
||||
|
||||
// Same idea but for method calls:
|
||||
|
||||
template <typename R, typename TC>
|
||||
struct ScriptInterface_NativeMethodWrapper {
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<TYPENAME_T0_HEAD(z,i) typename F> \
|
||||
static void call(JSContext* cx, JS::MutableHandleValue rval, TC* c, F fptr T0_A0_MAYBE_REF(z,i)) { \
|
||||
ScriptInterface::AssignOrToJSValUnrooted<R>(cx, rval, (c->*fptr)( A0(z,i) )); \
|
||||
}
|
||||
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
struct ScriptInterface_NativeMethodWrapper
|
||||
{
|
||||
template<typename F, typename... Ts>
|
||||
static void call(JSContext* cx, JS::MutableHandleValue rval, TC* c, F fptr, Ts... params)
|
||||
{
|
||||
ScriptInterface::AssignOrToJSValUnrooted<R>(cx, rval, (c->*fptr)(params...));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TC>
|
||||
struct ScriptInterface_NativeMethodWrapper<void, TC> {
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<TYPENAME_T0_HEAD(z,i) typename F> \
|
||||
static void call(JSContext* /*cx*/, JS::MutableHandleValue /*rval*/, TC* c, F fptr T0_A0_MAYBE_REF(z,i)) { \
|
||||
(c->*fptr)( A0(z,i) ); \
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
struct ScriptInterface_NativeMethodWrapper<void, TC>
|
||||
{
|
||||
template<typename F, typename... Ts>
|
||||
static void call(JSContext* UNUSED(cx), JS::MutableHandleValue UNUSED(rval), TC* c, F fptr, Ts... params)
|
||||
{
|
||||
(c->*fptr)(params...);
|
||||
}
|
||||
};
|
||||
|
||||
// JSFastNative-compatible function that wraps the function identified in the template argument list
|
||||
@ -126,7 +118,7 @@ struct ScriptInterface_NativeMethodWrapper<void, TC> {
|
||||
JSAutoRequest rq(cx); \
|
||||
BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
|
||||
JS::RootedValue rval(cx); \
|
||||
ScriptInterface_NativeWrapper<R>::template call<T0_HEAD(z,i) R( ScriptInterface::CxPrivate* T0_TAIL_MAYBE_REF(z,i))>(cx, &rval, fptr A0_TAIL(z,i)); \
|
||||
ScriptInterface_NativeWrapper<R>::template call<R( ScriptInterface::CxPrivate* T0_TAIL_MAYBE_REF(z,i)) T0_TAIL(z,i)>(cx, &rval, fptr A0_TAIL(z,i)); \
|
||||
args.rval().set(rval); \
|
||||
return !ScriptInterface::IsExceptionPending(cx); \
|
||||
}
|
||||
@ -146,7 +138,7 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
if (! c) return false; \
|
||||
BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
|
||||
JS::RootedValue rval(cx); \
|
||||
ScriptInterface_NativeMethodWrapper<R, TC>::template call<T0_HEAD(z,i) R (TC::*)(T0_MAYBE_REF(z,i))>(cx, &rval, c, fptr A0_TAIL(z,i)); \
|
||||
ScriptInterface_NativeMethodWrapper<R, TC>::template call<R (TC::*)(T0_MAYBE_REF(z,i)) T0_TAIL(z,i)>(cx, &rval, c, fptr A0_TAIL(z,i)); \
|
||||
args.rval().set(rval); \
|
||||
return !ScriptInterface::IsExceptionPending(cx); \
|
||||
}
|
||||
@ -166,65 +158,77 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
if (! c) return false; \
|
||||
BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
|
||||
JS::RootedValue rval(cx); \
|
||||
ScriptInterface_NativeMethodWrapper<R, TC>::template call<T0_HEAD(z,i) R (TC::*)(T0_MAYBE_REF(z,i)) const>(cx, &rval, c, fptr A0_TAIL(z,i)); \
|
||||
ScriptInterface_NativeMethodWrapper<R, TC>::template call<R (TC::*)(T0_MAYBE_REF(z,i)) const T0_TAIL(z,i)>(cx, &rval, c, fptr A0_TAIL(z,i)); \
|
||||
args.rval().set(rval); \
|
||||
return !ScriptInterface::IsExceptionPending(cx); \
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
#define ASSIGN_OR_TO_JS_VAL(z, i, data) AssignOrToJSVal(cx, argv[i], a##i);
|
||||
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name T0_A0_TAIL_CONST_REF(z,i), R& ret) const \
|
||||
{ \
|
||||
JSContext* cx = GetContext(); \
|
||||
JSAutoRequest rq(cx); \
|
||||
JS::RootedValue jsRet(cx); \
|
||||
JS::AutoValueVector argv(cx); \
|
||||
argv.resize(i); \
|
||||
BOOST_PP_REPEAT_##z (i, ASSIGN_OR_TO_JS_VAL, ~) \
|
||||
bool ok = CallFunction_(val, name, argv, &jsRet); \
|
||||
if (!ok) \
|
||||
return false; \
|
||||
return FromJSVal(cx, jsRet, ret); \
|
||||
template<int i, typename T, typename... Ts>
|
||||
static void AssignOrToJSValHelper(JSContext* cx, JS::AutoValueVector& argv, const T& a, const Ts&... params)
|
||||
{
|
||||
ScriptInterface::AssignOrToJSVal(cx, argv[i], a);
|
||||
AssignOrToJSValHelper<i+1>(cx, argv, params...);
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name T0_A0_TAIL_CONST_REF(z,i), JS::Rooted<R>* ret) const \
|
||||
{ \
|
||||
JSContext* cx = GetContext(); \
|
||||
JSAutoRequest rq(cx); \
|
||||
JS::MutableHandle<R> jsRet(ret); \
|
||||
JS::AutoValueVector argv(cx); \
|
||||
argv.resize(i); \
|
||||
BOOST_PP_REPEAT_##z (i, ASSIGN_OR_TO_JS_VAL, ~) \
|
||||
return CallFunction_(val, name, argv, jsRet); \
|
||||
template<int i, typename... Ts>
|
||||
static void AssignOrToJSValHelper(JSContext* UNUSED(cx), JS::AutoValueVector& UNUSED(argv))
|
||||
{
|
||||
cassert(sizeof...(Ts) == 0);
|
||||
// Nop, for terminating the template recursion.
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<typename R TYPENAME_T0_TAIL(z, i)> \
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name T0_A0_TAIL_CONST_REF(z,i), JS::MutableHandle<R> ret) const \
|
||||
{ \
|
||||
JSContext* cx = GetContext(); \
|
||||
JSAutoRequest rq(cx); \
|
||||
JS::AutoValueVector argv(cx); \
|
||||
argv.resize(i); \
|
||||
BOOST_PP_REPEAT_##z (i, ASSIGN_OR_TO_JS_VAL, ~) \
|
||||
bool ok = CallFunction_(val, name, argv, ret); \
|
||||
if (!ok) \
|
||||
return false; \
|
||||
return true; \
|
||||
template<typename R, typename... Ts>
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, R& ret, const Ts&... params) const
|
||||
{
|
||||
JSContext* cx = GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue jsRet(cx);
|
||||
JS::AutoValueVector argv(cx);
|
||||
argv.resize(sizeof...(Ts));
|
||||
AssignOrToJSValHelper<0>(cx, argv, params...);
|
||||
bool ok = CallFunction_(val, name, argv, &jsRet);
|
||||
if (!ok)
|
||||
return false;
|
||||
return FromJSVal(cx, jsRet, ret);
|
||||
}
|
||||
|
||||
template<typename R, typename... Ts>
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, JS::Rooted<R>* ret, const Ts&... params) const
|
||||
{
|
||||
JSContext* cx = GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::MutableHandle<R> jsRet(ret);
|
||||
JS::AutoValueVector argv(cx);
|
||||
argv.resize(sizeof...(Ts));
|
||||
AssignOrToJSValHelper<0>(cx, argv, params...);
|
||||
return CallFunction_(val, name, argv, jsRet);
|
||||
}
|
||||
|
||||
template<typename R, typename... Ts>
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, JS::MutableHandle<R> ret, const Ts&... params) const
|
||||
{
|
||||
JSContext* cx = GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::AutoValueVector argv(cx);
|
||||
argv.resize(sizeof...(Ts));
|
||||
AssignOrToJSValHelper<0>(cx, argv, params...);
|
||||
return CallFunction_(val, name, argv, ret);
|
||||
}
|
||||
|
||||
// Call the named property on the given object, with void return type
|
||||
template<typename... Ts>
|
||||
bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name, const Ts&... params) const
|
||||
{
|
||||
JSContext* cx = GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue jsRet(cx);
|
||||
JS::AutoValueVector argv(cx);
|
||||
argv.resize(sizeof...(Ts));
|
||||
AssignOrToJSValHelper<0>(cx, argv, params...);
|
||||
return CallFunction_(val, name, argv, &jsRet);
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
#undef ASSIGN_OR_TO_JS_VAL
|
||||
|
||||
// Clean up our mess
|
||||
#undef NUMBERED_LIST_HEAD
|
||||
@ -232,19 +236,10 @@ BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef NUMBERED_LIST_TAIL_MAYBE_REF
|
||||
#undef NUMBERED_LIST_BALANCED
|
||||
#undef NUMBERED_LIST_BALANCED_MAYBE_REF
|
||||
#undef TYPED_ARGS
|
||||
#undef TYPED_ARGS_MAYBE_REF
|
||||
#undef TYPED_ARGS_CONST_REF
|
||||
#undef CONVERT_ARG
|
||||
#undef TYPENAME_T0_HEAD
|
||||
#undef TYPENAME_T0_TAIL
|
||||
#undef T0
|
||||
#undef T0_MAYBE_REF
|
||||
#undef T0_HEAD
|
||||
#undef T0_TAIL
|
||||
#undef T0_TAIL_MAYBE_REF
|
||||
#undef T0_A0
|
||||
#undef T0_A0_MAYBE_REF
|
||||
#undef T0_A0_TAIL_CONST_REF
|
||||
#undef A0
|
||||
#undef A0_TAIL
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2016 Wildfire Games.
|
||||
/* Copyright (C) 2017 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -562,14 +562,6 @@ JSObject* ScriptInterface::CreateCustomObject(const std::string& typeName) const
|
||||
return JS_NewObjectWithGivenProto(m->m_cx, it->second.m_Class, prototype);
|
||||
}
|
||||
|
||||
bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name)
|
||||
{
|
||||
JSAutoRequest rq(m->m_cx);
|
||||
JS::RootedValue jsRet(m->m_cx);
|
||||
return CallFunction_(val, name, JS::HandleValueArray::empty(), &jsRet);
|
||||
}
|
||||
|
||||
|
||||
bool ScriptInterface::CallFunction_(JS::HandleValue val, const char* name, JS::HandleValueArray argv, JS::MutableHandleValue ret) const
|
||||
{
|
||||
JSAutoRequest rq(m->m_cx);
|
||||
|
@ -131,29 +131,6 @@ public:
|
||||
*/
|
||||
void CallConstructor(JS::HandleValue ctor, JS::HandleValueArray argv, JS::MutableHandleValue out);
|
||||
|
||||
/**
|
||||
* Call the named property on the given object, with void return type and 0 arguments
|
||||
*/
|
||||
bool CallFunctionVoid(JS::HandleValue val, const char* name);
|
||||
|
||||
/**
|
||||
* Call the named property on the given object, with void return type and 1 argument
|
||||
*/
|
||||
template<typename T0>
|
||||
bool CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0);
|
||||
|
||||
/**
|
||||
* Call the named property on the given object, with void return type and 2 arguments
|
||||
*/
|
||||
template<typename T0, typename T1>
|
||||
bool CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0, const T1& a1);
|
||||
|
||||
/**
|
||||
* Call the named property on the given object, with void return type and 3 arguments
|
||||
*/
|
||||
template<typename T0, typename T1, typename T2>
|
||||
bool CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0, const T1& a1, const T2& a2);
|
||||
|
||||
JSObject* CreateCustomObject(const std::string & typeName) const;
|
||||
void DefineCustomObjectType(JSClass *clasp, JSNative constructor, uint minArgs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
|
||||
|
||||
@ -443,8 +420,20 @@ public:
|
||||
// template <R, T0..., JSClass*, TC, TR (TC:*fptr) const (T0...)>
|
||||
// static JSNative callMethodConst;
|
||||
//
|
||||
// template <dummy, T0...>
|
||||
// template <T0...>
|
||||
// static size_t nargs();
|
||||
//
|
||||
// template <R, T0...>
|
||||
// bool CallFunction(JS::HandleValue val, const char* name, R& ret, const T0&...) const;
|
||||
//
|
||||
// template <R, T0...>
|
||||
// bool CallFunction(JS::HandleValue val, const char* name, JS::Rooted<R>* ret, const T0&...) const;
|
||||
//
|
||||
// template <R, T0...>
|
||||
// bool CallFunction(JS::HandleValue val, const char* name, JS::MutableHandle<R> ret, const T0&...) const;
|
||||
//
|
||||
// template <T0...>
|
||||
// bool CallFunctionVoid(JS::HandleValue val, const char* name, const T0&...) const;
|
||||
};
|
||||
|
||||
// Implement those declared functions
|
||||
@ -495,45 +484,6 @@ inline JS::HandleValue ScriptInterface::AssignOrFromJSVal<JS::HandleValue>(JSCon
|
||||
return val;
|
||||
}
|
||||
|
||||
template<typename T0>
|
||||
bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0)
|
||||
{
|
||||
JSContext* cx = GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue jsRet(cx);
|
||||
JS::AutoValueVector argv(cx);
|
||||
argv.resize(1);
|
||||
AssignOrToJSVal(cx, argv[0], a0);
|
||||
return CallFunction_(val, name, argv, &jsRet);
|
||||
}
|
||||
|
||||
template<typename T0, typename T1>
|
||||
bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0, const T1& a1)
|
||||
{
|
||||
JSContext* cx = GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue jsRet(cx);
|
||||
JS::AutoValueVector argv(cx);
|
||||
argv.resize(2);
|
||||
AssignOrToJSVal(cx, argv[0], a0);
|
||||
AssignOrToJSVal(cx, argv[1], a1);
|
||||
return CallFunction_(val, name, argv, &jsRet);
|
||||
}
|
||||
|
||||
template<typename T0, typename T1, typename T2>
|
||||
bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name, const T0& a0, const T1& a1, const T2& a2)
|
||||
{
|
||||
JSContext* cx = GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
JS::RootedValue jsRet(cx);
|
||||
JS::AutoValueVector argv(cx);
|
||||
argv.resize(3);
|
||||
AssignOrToJSVal(cx, argv[0], a0);
|
||||
AssignOrToJSVal(cx, argv[1], a1);
|
||||
AssignOrToJSVal(cx, argv[2], a2);
|
||||
return CallFunction_(val, name, argv, &jsRet);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ScriptInterface::SetGlobal(const char* name, const T& value, bool replace)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2016 Wildfire Games.
|
||||
/* Copyright (C) 2017 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -45,7 +45,7 @@ class TestScriptConversions : public CxxTest::TestSuite
|
||||
// since they might not be objects. So just use uneval.
|
||||
std::string source;
|
||||
JS::RootedValue global(cx, script.GetGlobalObject());
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", v1, source));
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", source, v1));
|
||||
|
||||
TS_ASSERT_STR_EQUALS(source, expected);
|
||||
}
|
||||
@ -63,7 +63,7 @@ class TestScriptConversions : public CxxTest::TestSuite
|
||||
|
||||
std::string source;
|
||||
JS::RootedValue global(cx, script.GetGlobalObject());
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", v1, source));
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", source, v1));
|
||||
|
||||
if (expected)
|
||||
TS_ASSERT_STR_EQUALS(source, expected);
|
||||
@ -89,12 +89,12 @@ class TestScriptConversions : public CxxTest::TestSuite
|
||||
T r;
|
||||
JS::RootedValue r1(cx);
|
||||
|
||||
TS_ASSERT(script.CallFunction(u1, func.c_str(), v1, r));
|
||||
TS_ASSERT(script.CallFunction(u1, func.c_str(), r, v1));
|
||||
ScriptInterface::ToJSVal(cx, &r1, r);
|
||||
|
||||
std::string source;
|
||||
JS::RootedValue global(cx, script.GetGlobalObject());
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", r1, source));
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", source, r1));
|
||||
|
||||
TS_ASSERT_STR_EQUALS(source, expected);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
/* Copyright (C) 2017 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -170,7 +170,7 @@ public:
|
||||
TS_ASSERT_EQUALS(4, nbr);
|
||||
|
||||
// CallFunction const JS::RootedValue& parameter overload
|
||||
script.CallFunction(val, "add", nbrVal, nbr);
|
||||
script.CallFunction(val, "add", nbr, nbrVal);
|
||||
TS_ASSERT_EQUALS(7, nbr);
|
||||
|
||||
// GetProperty JS::RootedValue* overload
|
||||
@ -202,7 +202,7 @@ public:
|
||||
TS_ASSERT_EQUALS(4, nbr);
|
||||
|
||||
// CallFunction const JS::HandleValue& parameter overload
|
||||
script.CallFunction(val, "add", nbrVal, nbr);
|
||||
script.CallFunction(val, "add", nbr, nbrVal);
|
||||
TS_ASSERT_EQUALS(7, nbr);
|
||||
|
||||
// GetProperty JS::MutableHandleValue overload
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
/* Copyright (C) 2017 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -32,11 +32,11 @@ public:
|
||||
|
||||
virtual void GetRepresentation(JS::MutableHandleValue ret)
|
||||
{
|
||||
return m_Script.CallRef("GetRepresentation", ret);
|
||||
m_Script.CallRef("GetRepresentation", ret);
|
||||
}
|
||||
virtual void GetFullRepresentation(JS::MutableHandleValue ret, bool flushEvents = false)
|
||||
{
|
||||
return m_Script.CallRef("GetFullRepresentation",flushEvents, ret);
|
||||
m_Script.CallRef("GetFullRepresentation", ret, flushEvents);
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2012 Wildfire Games.
|
||||
/* Copyright (C) 2017 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -32,7 +32,7 @@ public:
|
||||
|
||||
virtual void GetAllTechs(JS::MutableHandleValue ret)
|
||||
{
|
||||
return m_Script.CallRef("GetAllTechs", ret);
|
||||
m_Script.CallRef("GetAllTechs", ret);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2010 Wildfire Games.
|
||||
/* Copyright (C) 2017 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -32,7 +32,7 @@ public:
|
||||
|
||||
virtual void ScriptCall(int player, const std::wstring& cmd, JS::HandleValue data, JS::MutableHandleValue ret)
|
||||
{
|
||||
m_Script.CallRef("ScriptCall", player, cmd, data, ret);
|
||||
m_Script.CallRef("ScriptCall", ret, player, cmd, data);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -22,10 +22,6 @@
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
|
||||
|
||||
class CSimContext;
|
||||
class CParamNode;
|
||||
class ISerializer;
|
||||
@ -33,6 +29,7 @@ class IDeserializer;
|
||||
|
||||
class CComponentTypeScript
|
||||
{
|
||||
NONCOPYABLE(CComponentTypeScript);
|
||||
public:
|
||||
CComponentTypeScript(ScriptInterface& scriptInterface, JS::HandleValue instance);
|
||||
|
||||
@ -45,43 +42,30 @@ public:
|
||||
void Serialize(ISerializer& serialize);
|
||||
void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize, entity_id_t ent);
|
||||
|
||||
// Use Boost.PP to define:
|
||||
// template<typename R> R Call(const char* funcname) const;
|
||||
// template<typename R, typename T0> R Call(const char* funcname, const T0& a0) const;
|
||||
// ...
|
||||
// template<typename R> void CallRef(const char* funcname, R ret) const;
|
||||
// template<typename R, typename T0> void CallRef(const char* funcname, const T0& a0, R ret) const;
|
||||
// ...
|
||||
// void CallVoid(const char* funcname) const;
|
||||
// template<typename T0> void CallVoid(const char* funcname, const T0& a0) const;
|
||||
// ...
|
||||
|
||||
// CallRef is mainly used for returning script values with correct stack rooting.
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(i, typename T)> \
|
||||
R Call(const char* funcname BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(i, const T, &a)) const \
|
||||
{ \
|
||||
R ret; \
|
||||
if (m_ScriptInterface.CallFunction(m_Instance, funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a), ret)) \
|
||||
return ret; \
|
||||
LOGERROR("Error calling component script function %s", funcname); \
|
||||
return R(); \
|
||||
} \
|
||||
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(i, typename T)> \
|
||||
void CallRef(const char* funcname BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(i, const T, &a), R ret) const \
|
||||
{ \
|
||||
if (!m_ScriptInterface.CallFunction(m_Instance, funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a), ret)) \
|
||||
LOGERROR("Error calling component script function %s", funcname); \
|
||||
} \
|
||||
BOOST_PP_IF(i, template<, ) BOOST_PP_ENUM_PARAMS(i, typename T) BOOST_PP_IF(i, >, ) \
|
||||
void CallVoid(const char* funcname BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(i, const T, &a)) const \
|
||||
{ \
|
||||
if (m_ScriptInterface.CallFunctionVoid(m_Instance, funcname BOOST_PP_ENUM_TRAILING_PARAMS(i, a))) \
|
||||
return; \
|
||||
LOGERROR("Error calling component script function %s", funcname); \
|
||||
template<typename R, typename... Ts>
|
||||
R Call(const char* funcname, const Ts&... params) const
|
||||
{
|
||||
R ret;
|
||||
if (m_ScriptInterface.CallFunction(m_Instance, funcname, ret, params...))
|
||||
return ret;
|
||||
LOGERROR("Error calling component script function %s", funcname);
|
||||
return R();
|
||||
}
|
||||
|
||||
// CallRef is mainly used for returning script values with correct stack rooting.
|
||||
template<typename R, typename... Ts>
|
||||
void CallRef(const char* funcname, R ret, const Ts&... params) const
|
||||
{
|
||||
if (!m_ScriptInterface.CallFunction(m_Instance, funcname, ret, params...))
|
||||
LOGERROR("Error calling component script function %s", funcname);
|
||||
}
|
||||
|
||||
template<typename... Ts>
|
||||
void CallVoid(const char* funcname, const Ts&... params) const
|
||||
{
|
||||
if (!m_ScriptInterface.CallFunctionVoid(m_Instance, funcname, params...))
|
||||
LOGERROR("Error calling component script function %s", funcname);
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
private:
|
||||
ScriptInterface& m_ScriptInterface;
|
||||
@ -89,8 +73,6 @@ private:
|
||||
bool m_HasCustomSerialize;
|
||||
bool m_HasCustomDeserialize;
|
||||
bool m_HasNullSerialize;
|
||||
|
||||
NONCOPYABLE(CComponentTypeScript);
|
||||
};
|
||||
|
||||
#endif // INCLUDED_SCRIPTCOMPONENT
|
||||
|
Loading…
Reference in New Issue
Block a user