Replace ScriptInterface::Call* with new ScriptFunction functions
Finishes work started in f3aedf88a6
.
This removes the boost-CPP function wrappers entirely, in favour of pure
templated code in FunctionWrapper.h
The Call* functions were already heavily templated, so there is nothing
really new here. I just use tag dispatch to reduce the number of
overloads slightly.
The new functions do not need the script interface, only the script
request.
Differential Revision: https://code.wildfiregames.com/D3912
This was SVN commit r25354.
This commit is contained in:
parent
d9748173c7
commit
d46a417748
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -26,6 +26,7 @@
|
||||
#include "ps/GameSetup/Config.h"
|
||||
#include "ps/Profile.h"
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptContext.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
|
||||
@ -137,7 +138,7 @@ void CGUIManager::SGUIPage::LoadPage(shared_ptr<ScriptContext> scriptContext)
|
||||
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
JS::RootedValue hotloadDataVal(rq.cx);
|
||||
scriptInterface->CallFunction(global, "getHotloadData", &hotloadDataVal);
|
||||
ScriptFunction::Call(rq, global, "getHotloadData", &hotloadDataVal);
|
||||
hotloadData = scriptInterface->WriteStructuredClone(hotloadDataVal);
|
||||
}
|
||||
|
||||
@ -212,7 +213,7 @@ void CGUIManager::SGUIPage::LoadPage(shared_ptr<ScriptContext> scriptContext)
|
||||
scriptInterface->ReadStructuredClone(hotloadData, &hotloadDataVal);
|
||||
|
||||
if (scriptInterface->HasProperty(global, "init") &&
|
||||
!scriptInterface->CallFunctionVoid(global, "init", initDataVal, hotloadDataVal))
|
||||
!ScriptFunction::CallVoid(rq, global, "init", initDataVal, hotloadDataVal))
|
||||
LOGERROR("GUI page '%s': Failed to call init() function", utf8_from_wstring(m_Name));
|
||||
}
|
||||
|
||||
@ -301,7 +302,7 @@ InReaction CGUIManager::HandleEvent(const SDL_Event_* ev)
|
||||
ScriptRequest rq(*top()->GetScriptInterface());
|
||||
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
if (top()->GetScriptInterface()->CallFunction(global, "handleInputBeforeGui", handled, *ev, top()->FindObjectUnderMouse()))
|
||||
if (ScriptFunction::Call(rq, global, "handleInputBeforeGui", handled, *ev, top()->FindObjectUnderMouse()))
|
||||
if (handled)
|
||||
return IN_HANDLED;
|
||||
}
|
||||
@ -319,7 +320,7 @@ InReaction CGUIManager::HandleEvent(const SDL_Event_* ev)
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
|
||||
PROFILE("handleInputAfterGui");
|
||||
if (top()->GetScriptInterface()->CallFunction(global, "handleInputAfterGui", handled, *ev))
|
||||
if (ScriptFunction::Call(rq, global, "handleInputAfterGui", handled, *ev))
|
||||
if (handled)
|
||||
return IN_HANDLED;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/TimeManager.h"
|
||||
#include "renderer/WaterManager.h"
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "simulation2/Simulation2.h"
|
||||
#include "simulation2/components/ICmpPlayer.h"
|
||||
@ -328,7 +329,7 @@ PSRETURN CGame::ReallyStartGame()
|
||||
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
if (scriptInterface->HasProperty(global, "reallyStartGame"))
|
||||
scriptInterface->CallFunctionVoid(global, "reallyStartGame");
|
||||
ScriptFunction::CallVoid(rq, global, "reallyStartGame");
|
||||
}
|
||||
|
||||
debug_printf("GAME STARTED, ALL INIT COMPLETE\n");
|
||||
|
@ -78,6 +78,7 @@
|
||||
#include "renderer/Renderer.h"
|
||||
#include "renderer/VertexBufferManager.h"
|
||||
#include "renderer/ModelRenderer.h"
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "scriptinterface/ScriptStats.h"
|
||||
#include "scriptinterface/ScriptContext.h"
|
||||
@ -1631,7 +1632,7 @@ void CancelLoad(const CStrW& message)
|
||||
if (g_GUI &&
|
||||
g_GUI->GetPageCount() &&
|
||||
pScriptInterface->HasProperty(global, "cancelOnLoadGameError"))
|
||||
pScriptInterface->CallFunctionVoid(global, "cancelOnLoadGameError", message);
|
||||
ScriptFunction::CallVoid(rq, global, "cancelOnLoadGameError", message);
|
||||
}
|
||||
|
||||
bool InDevelopmentCopy()
|
||||
|
@ -226,7 +226,7 @@ void RunHardwareDetection()
|
||||
|
||||
// Run the detection script:
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
scriptInterface.CallFunctionVoid(global, "RunHardwareDetection", settings);
|
||||
ScriptFunction::CallVoid(rq, global, "RunHardwareDetection", settings);
|
||||
}
|
||||
|
||||
static void ReportSDL(const ScriptInterface& scriptInterface, JS::HandleValue settings)
|
||||
|
@ -207,6 +207,71 @@ private:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct IgnoreResult_t {};
|
||||
static inline IgnoreResult_t IgnoreResult;
|
||||
|
||||
/**
|
||||
* Recursive helper to call AssignOrToJSVal
|
||||
*/
|
||||
template<int i, typename T, typename... Ts>
|
||||
static void AssignOrToJSValHelper(const ScriptRequest& rq, JS::MutableHandleValueVector argv, const T& a, const Ts&... params)
|
||||
{
|
||||
ScriptInterface::AssignOrToJSVal(rq, argv[i], a);
|
||||
AssignOrToJSValHelper<i+1>(rq, argv, params...);
|
||||
}
|
||||
|
||||
template<int i, typename... Ts>
|
||||
static void AssignOrToJSValHelper(const ScriptRequest& UNUSED(rq), JS::MutableHandleValueVector UNUSED(argv))
|
||||
{
|
||||
static_assert(sizeof...(Ts) == 0);
|
||||
// Nop, for terminating the template recursion.
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around calling a JS function from C++.
|
||||
* Arguments are const& to avoid lvalue/rvalue issues, and so can't be used as out-parameters.
|
||||
* In particular, the problem is that Rooted are deduced as Rooted, not Handle, and so can't be copied.
|
||||
* This could be worked around with more templates, but it doesn't seem particularly worth doing.
|
||||
*/
|
||||
template<typename R, typename ...Args>
|
||||
static bool Call_(const ScriptRequest& rq, JS::HandleValue val, const char* name, R& ret, const Args&... args)
|
||||
{
|
||||
JS::RootedObject obj(rq.cx);
|
||||
if (!JS_ValueToObject(rq.cx, val, &obj) || !obj)
|
||||
return false;
|
||||
|
||||
// Check that the named function actually exists, to avoid ugly JS error reports
|
||||
// when calling an undefined value
|
||||
bool found;
|
||||
if (!JS_HasProperty(rq.cx, obj, name, &found) || !found)
|
||||
return false;
|
||||
|
||||
JS::RootedValueVector argv(rq.cx);
|
||||
ignore_result(argv.resize(sizeof...(Args)));
|
||||
AssignOrToJSValHelper<0>(rq, &argv, args...);
|
||||
|
||||
bool success;
|
||||
if constexpr (std::is_same_v<R, JS::MutableHandleValue>)
|
||||
success = JS_CallFunctionName(rq.cx, obj, name, argv, ret);
|
||||
else
|
||||
{
|
||||
JS::RootedValue jsRet(rq.cx);
|
||||
success = JS_CallFunctionName(rq.cx, obj, name, argv, &jsRet);
|
||||
if constexpr (!std::is_same_v<R, IgnoreResult_t>)
|
||||
{
|
||||
if (success)
|
||||
ScriptInterface::FromJSVal(rq, jsRet, ret);
|
||||
}
|
||||
else
|
||||
UNUSED2(ret); // VS2017 complains.
|
||||
}
|
||||
// Even if everything succeeded, there could be pending exceptions
|
||||
return !ScriptException::CatchPending(rq) && success;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
template <typename T>
|
||||
using ObjectGetter = T*(*)(const ScriptRequest&, JS::CallArgs&);
|
||||
@ -279,6 +344,34 @@ public:
|
||||
return !ScriptException::IsPending(rq);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a JS function @a name, property of object @a val, with the arguments @a args.
|
||||
* @a ret will be updated with the return value, if any.
|
||||
* @return the success (or failure) thereof.
|
||||
*/
|
||||
template<typename R, typename ...Args>
|
||||
static bool Call(const ScriptRequest& rq, JS::HandleValue val, const char* name, R& ret, const Args&... args)
|
||||
{
|
||||
return Call_(rq, val, name, ret, std::forward<const Args>(args)...);
|
||||
}
|
||||
|
||||
// Specialisation for MutableHandleValue return.
|
||||
template<typename ...Args>
|
||||
static bool Call(const ScriptRequest& rq, JS::HandleValue val, const char* name, JS::MutableHandleValue ret, const Args&... args)
|
||||
{
|
||||
return Call_(rq, val, name, ret, std::forward<const Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a JS function @a name, property of object @a val, with the arguments @a args.
|
||||
* @return the success (or failure) thereof.
|
||||
*/
|
||||
template<typename ...Args>
|
||||
static bool CallVoid(const ScriptRequest& rq, JS::HandleValue val, const char* name, const Args&... args)
|
||||
{
|
||||
return Call(rq, val, name, IgnoreResult, std::forward<const Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a function spec from a C++ function.
|
||||
*/
|
||||
|
@ -1,102 +0,0 @@
|
||||
/* 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
|
||||
// MaybeRef should be private, but has to be public due to a compiler bug in clang.
|
||||
// TODO: Make this private when the bug is fixed in all supported versions of clang.
|
||||
template <typename T> struct MaybeRef;
|
||||
|
||||
// Define lots of useful macros:
|
||||
|
||||
// Varieties of comma-separated list to fit on the head/tail/whole of another comma-separated list
|
||||
#define NUMBERED_LIST_HEAD(z, i, data) data##i,
|
||||
#define NUMBERED_LIST_TAIL(z, i, data) ,data##i
|
||||
#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
|
||||
|
||||
// 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
|
||||
// behaviour because some types have undefined values when not being initialized).
|
||||
// This is not very clear and also a bit fragile. Another problem is that the error reporting lacks
|
||||
// a bit. SpiderMonkey will throw a JS exception and abort the execution of the current function when
|
||||
// we return false here (without printing a callstack or additional detail telling that an argument
|
||||
// conversion failed). So we have two TODOs here:
|
||||
// 1. On the conceptual side: How to consistently work with optional parameters (or drop them completely?)
|
||||
// 2. On the technical side: Improve error handling, find a better way to ensure parameters are initialized
|
||||
#define CONVERT_ARG(z, i, data) \
|
||||
bool typeConvRet##i; \
|
||||
T##i a##i = ScriptInterface::AssignOrFromJSVal<T##i>( \
|
||||
rq, \
|
||||
i < args.length() ? args[i] : JS::UndefinedHandleValue, \
|
||||
typeConvRet##i); \
|
||||
if (!typeConvRet##i) return false;
|
||||
|
||||
// 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 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_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 A0_TAIL(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_TAIL, a) // ", a0, a1"
|
||||
|
||||
// JSFastNative-compatible function that wraps the function identified in the template argument list
|
||||
// (Definition comes later, since it depends on some things we haven't defined yet)
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R, TYPENAME_T0_HEAD(z,i) R (*fptr) ( ScriptInterface::CmptPrivate* T0_TAIL_MAYBE_REF(z,i) )> \
|
||||
static bool call(JSContext* cx, uint argc, JS::Value* vp);
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
// Similar, for class methods
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R, TYPENAME_T0_HEAD(z,i) JSClass* CLS, typename TC, R (TC::*fptr) ( T0_MAYBE_REF(z,i) )> \
|
||||
static bool callMethod(JSContext* cx, uint argc, JS::Value* vp);
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
// const methods
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R, TYPENAME_T0_HEAD(z,i) JSClass* CLS, typename TC, R (TC::*fptr) ( T0_MAYBE_REF(z,i) ) const> \
|
||||
static bool callMethodConst(JSContext* cx, uint argc, JS::Value* vp);
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
// Argument-number counter
|
||||
template<typename... Ts>
|
||||
static size_t nargs() { return sizeof...(Ts); }
|
||||
|
||||
// Call the named property on the given object
|
||||
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).
|
||||
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.
|
||||
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;
|
@ -1,235 +0,0 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Use the macro below to define types that will be passed by value to C++ functions.
|
||||
// NOTE: References are used just to avoid superfluous copy constructor calls
|
||||
// in the script wrapper code. They cannot be used as out-parameters.
|
||||
// They are const T& by default to avoid confusion about this, especially
|
||||
// because sometimes the function is not just exposed to scripts, but also
|
||||
// called from C++ code.
|
||||
|
||||
template <typename T> struct ScriptInterface::MaybeRef
|
||||
{
|
||||
typedef const T& Type;
|
||||
};
|
||||
|
||||
#define PASS_BY_VALUE_IN_NATIVE_WRAPPER(T) \
|
||||
template <> struct ScriptInterface::MaybeRef<T> \
|
||||
{ \
|
||||
typedef T Type; \
|
||||
}; \
|
||||
|
||||
PASS_BY_VALUE_IN_NATIVE_WRAPPER(JS::HandleValue)
|
||||
PASS_BY_VALUE_IN_NATIVE_WRAPPER(bool)
|
||||
PASS_BY_VALUE_IN_NATIVE_WRAPPER(int)
|
||||
PASS_BY_VALUE_IN_NATIVE_WRAPPER(uint8_t)
|
||||
PASS_BY_VALUE_IN_NATIVE_WRAPPER(uint16_t)
|
||||
PASS_BY_VALUE_IN_NATIVE_WRAPPER(uint32_t)
|
||||
PASS_BY_VALUE_IN_NATIVE_WRAPPER(fixed)
|
||||
PASS_BY_VALUE_IN_NATIVE_WRAPPER(float)
|
||||
PASS_BY_VALUE_IN_NATIVE_WRAPPER(double)
|
||||
|
||||
#undef PASS_BY_VALUE_IN_NATIVE_WRAPPER
|
||||
|
||||
// This works around a bug in Visual Studio (error C2244 if ScriptInterface:: is included in the
|
||||
// type specifier of MaybeRef<T>::Type for parameters inside the member function declaration).
|
||||
// It's probably the bug described here, but I'm not quite sure (at least the example there still
|
||||
// cause error C2244):
|
||||
// https://connect.microsoft.com/VisualStudio/feedback/details/611863/vs2010-c-fails-with-error-c2244-gcc-4-3-4-compiles-ok
|
||||
//
|
||||
// TODO: When dropping support for VS 2015, check if this bug is still present in the supported
|
||||
// Visual Studio versions (replace the macro definitions in NativeWrapperDecls.h with these ones,
|
||||
// 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
|
||||
#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
|
||||
|
||||
// (NativeWrapperDecls.h set up a lot of the macros we use here)
|
||||
|
||||
// ScriptInterface_NativeWrapper<T>::call(rq, rval, fptr, args...) will call fptr(cbdata, args...),
|
||||
// and if T != void then it will store the result in rval:
|
||||
|
||||
// Templated on the return type so void can be handled separately
|
||||
template <typename R>
|
||||
struct ScriptInterface_NativeWrapper
|
||||
{
|
||||
template<typename F, typename... Ts>
|
||||
static void call(const ScriptRequest& rq, JS::MutableHandleValue rval, F fptr, Ts... params)
|
||||
{
|
||||
ScriptInterface::AssignOrToJSValUnrooted<R>(rq, rval, fptr(ScriptInterface::GetScriptInterfaceAndCBData(rq.cx), params...));
|
||||
}
|
||||
};
|
||||
|
||||
// Overloaded to ignore the return value from void functions
|
||||
template <>
|
||||
struct ScriptInterface_NativeWrapper<void>
|
||||
{
|
||||
template<typename F, typename... Ts>
|
||||
static void call(const ScriptRequest& rq, JS::MutableHandleValue UNUSED(rval), F fptr, Ts... params)
|
||||
{
|
||||
fptr(ScriptInterface::GetScriptInterfaceAndCBData(rq.cx), params...);
|
||||
}
|
||||
};
|
||||
|
||||
// Same idea but for method calls:
|
||||
|
||||
template <typename R, typename TC>
|
||||
struct ScriptInterface_NativeMethodWrapper
|
||||
{
|
||||
template<typename F, typename... Ts>
|
||||
static void call(const ScriptRequest& rq, JS::MutableHandleValue rval, TC* c, F fptr, Ts... params)
|
||||
{
|
||||
ScriptInterface::AssignOrToJSValUnrooted<R>(rq, rval, (c->*fptr)(params...));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TC>
|
||||
struct ScriptInterface_NativeMethodWrapper<void, TC>
|
||||
{
|
||||
template<typename F, typename... Ts>
|
||||
static void call(const ScriptRequest& UNUSED(rq), 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
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R, TYPENAME_T0_HEAD(z,i) R (*fptr) ( ScriptInterface::CmptPrivate* T0_TAIL_MAYBE_REF(z,i) )> \
|
||||
bool ScriptInterface::call(JSContext* cx, uint argc, JS::Value* vp) \
|
||||
{ \
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp); \
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
|
||||
BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
|
||||
JS::RootedValue rval(rq.cx); \
|
||||
ScriptInterface_NativeWrapper<R>::template call<R( ScriptInterface::CmptPrivate* T0_TAIL_MAYBE_REF(z,i)) T0_TAIL(z,i)>(rq, &rval, fptr A0_TAIL(z,i)); \
|
||||
args.rval().set(rval); \
|
||||
return !ScriptException::IsPending(rq); \
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
// Same idea but for methods
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R, TYPENAME_T0_HEAD(z,i) JSClass* CLS, typename TC, R (TC::*fptr) ( T0_MAYBE_REF(z,i) )> \
|
||||
bool ScriptInterface::callMethod(JSContext* cx, uint argc, JS::Value* vp) \
|
||||
{ \
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp); \
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
|
||||
TC* c = ScriptInterface::GetPrivate<TC>(rq, args, CLS); \
|
||||
if (! c) return false; \
|
||||
BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
|
||||
JS::RootedValue rval(rq.cx); \
|
||||
ScriptInterface_NativeMethodWrapper<R, TC>::template call<R (TC::*)(T0_MAYBE_REF(z,i)) T0_TAIL(z,i)>(rq, &rval, c, fptr A0_TAIL(z,i)); \
|
||||
args.rval().set(rval); \
|
||||
return !ScriptException::IsPending(rq); \
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
// const methods
|
||||
#define OVERLOADS(z, i, data) \
|
||||
template <typename R, TYPENAME_T0_HEAD(z,i) JSClass* CLS, typename TC, R (TC::*fptr) ( T0_MAYBE_REF(z,i) ) const> \
|
||||
bool ScriptInterface::callMethodConst(JSContext* cx, uint argc, JS::Value* vp) \
|
||||
{ \
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp); \
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
|
||||
TC* c = ScriptInterface::GetPrivate<TC>(rq, args, CLS); \
|
||||
if (! c) return false; \
|
||||
BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \
|
||||
JS::RootedValue rval(rq.cx); \
|
||||
ScriptInterface_NativeMethodWrapper<R, TC>::template call<R (TC::*)(T0_MAYBE_REF(z,i)) const T0_TAIL(z,i)>(rq, &rval, c, fptr A0_TAIL(z,i)); \
|
||||
args.rval().set(rval); \
|
||||
return !ScriptException::IsPending(rq); \
|
||||
}
|
||||
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
|
||||
#undef OVERLOADS
|
||||
|
||||
template<int i, typename T, typename... Ts>
|
||||
static void AssignOrToJSValHelper(const ScriptRequest& rq, JS::MutableHandleValueVector argv, const T& a, const Ts&... params)
|
||||
{
|
||||
ScriptInterface::AssignOrToJSVal(rq, argv[i], a);
|
||||
AssignOrToJSValHelper<i+1>(rq, argv, params...);
|
||||
}
|
||||
|
||||
template<int i, typename... Ts>
|
||||
static void AssignOrToJSValHelper(const ScriptRequest& UNUSED(rq), JS::MutableHandleValueVector UNUSED(argv))
|
||||
{
|
||||
cassert(sizeof...(Ts) == 0);
|
||||
// Nop, for terminating the template recursion.
|
||||
}
|
||||
|
||||
template<typename R, typename... Ts>
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, R& ret, const Ts&... params) const
|
||||
{
|
||||
ScriptRequest rq(this);
|
||||
JS::RootedValue jsRet(rq.cx);
|
||||
JS::RootedValueVector argv(rq.cx);
|
||||
ignore_result(argv.resize(sizeof...(Ts)));
|
||||
AssignOrToJSValHelper<0>(rq, &argv, params...);
|
||||
if (!CallFunction_(val, name, argv, &jsRet))
|
||||
return false;
|
||||
return FromJSVal(rq, jsRet, ret);
|
||||
}
|
||||
|
||||
template<typename R, typename... Ts>
|
||||
bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, JS::Rooted<R>* ret, const Ts&... params) const
|
||||
{
|
||||
ScriptRequest rq(this);
|
||||
JS::MutableHandle<R> jsRet(ret);
|
||||
JS::RootedValueVector argv(rq.cx);
|
||||
ignore_result(argv.resize(sizeof...(Ts)));
|
||||
AssignOrToJSValHelper<0>(rq, &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
|
||||
{
|
||||
ScriptRequest rq(this);
|
||||
JS::RootedValueVector argv(rq.cx);
|
||||
ignore_result(argv.resize(sizeof...(Ts)));
|
||||
AssignOrToJSValHelper<0>(rq, &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
|
||||
{
|
||||
ScriptRequest rq(this);
|
||||
JS::RootedValue jsRet(rq.cx);
|
||||
JS::RootedValueVector argv(rq.cx);
|
||||
ignore_result(argv.resize(sizeof...(Ts)));
|
||||
AssignOrToJSValHelper<0>(rq, &argv, params...);
|
||||
return CallFunction_(val, name, argv, &jsRet);
|
||||
}
|
||||
|
||||
// Clean up our mess
|
||||
#undef NUMBERED_LIST_HEAD
|
||||
#undef NUMBERED_LIST_TAIL
|
||||
#undef NUMBERED_LIST_TAIL_MAYBE_REF
|
||||
#undef NUMBERED_LIST_BALANCED
|
||||
#undef NUMBERED_LIST_BALANCED_MAYBE_REF
|
||||
#undef CONVERT_ARG
|
||||
#undef TYPENAME_T0_HEAD
|
||||
#undef T0
|
||||
#undef T0_MAYBE_REF
|
||||
#undef T0_TAIL
|
||||
#undef T0_TAIL_MAYBE_REF
|
||||
#undef A0_TAIL
|
@ -472,26 +472,6 @@ JSObject* ScriptInterface::CreateCustomObject(const std::string& typeName) const
|
||||
return JS_NewObjectWithGivenProto(rq.cx, it->second.m_Class, prototype);
|
||||
}
|
||||
|
||||
bool ScriptInterface::CallFunction_(JS::HandleValue val, const char* name, JS::HandleValueArray argv, JS::MutableHandleValue ret) const
|
||||
{
|
||||
ScriptRequest rq(this);
|
||||
JS::RootedObject obj(rq.cx);
|
||||
if (!JS_ValueToObject(rq.cx, val, &obj) || !obj)
|
||||
return false;
|
||||
|
||||
// Check that the named function actually exists, to avoid ugly JS error reports
|
||||
// when calling an undefined value
|
||||
bool found;
|
||||
if (!JS_HasProperty(rq.cx, obj, name, &found) || !found)
|
||||
return false;
|
||||
|
||||
if (JS_CallFunctionName(rq.cx, obj, name, argv, ret))
|
||||
return true;
|
||||
|
||||
ScriptException::CatchPending(rq);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScriptInterface::CreateObject_(const ScriptRequest& rq, JS::MutableHandleObject object)
|
||||
{
|
||||
object.set(JS_NewPlainObject(rq.cx));
|
||||
@ -977,7 +957,7 @@ std::string ScriptInterface::ToString(JS::MutableHandleValue obj, bool pretty) c
|
||||
// so fall back to obj.toSource()
|
||||
|
||||
std::wstring source = L"(error)";
|
||||
CallFunction(obj, "toSource", source);
|
||||
ScriptFunction::Call(rq, obj, "toSource", source);
|
||||
return utf8_from_wstring(source);
|
||||
}
|
||||
|
||||
|
@ -442,7 +442,6 @@ private:
|
||||
return CreateObject_(rq, obj, args...) && JS_DefineProperty(rq.cx, obj, propertyName, val, JSPROP_ENUMERATE);
|
||||
}
|
||||
|
||||
bool CallFunction_(JS::HandleValue val, const char* name, JS::HandleValueArray argv, JS::MutableHandleValue ret) const;
|
||||
bool SetGlobal_(const char* name, JS::HandleValue value, bool replace, bool constant, bool enumerate);
|
||||
bool SetProperty_(JS::HandleValue obj, const char* name, JS::HandleValue value, bool constant, bool enumerate) const;
|
||||
bool SetProperty_(JS::HandleValue obj, const wchar_t* name, JS::HandleValue value, bool constant, bool enumerate) const;
|
||||
@ -461,40 +460,8 @@ private:
|
||||
|
||||
boost::random::rand48* m_rng;
|
||||
std::map<std::string, CustomType> m_CustomObjectTypes;
|
||||
|
||||
// The nasty macro/template bits are split into a separate file so you don't have to look at them
|
||||
public:
|
||||
#include "NativeWrapperDecls.h"
|
||||
// This declares:
|
||||
//
|
||||
// template <R, T0..., TR (*fptr) (void* cbdata, T0...)>
|
||||
// static JSNative call;
|
||||
//
|
||||
// template <R, T0..., JSClass*, TC, TR (TC:*fptr) (T0...)>
|
||||
// static JSNative callMethod;
|
||||
//
|
||||
// template <R, T0..., JSClass*, TC, TR (TC:*fptr) const (T0...)>
|
||||
// static JSNative callMethodConst;
|
||||
//
|
||||
// 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
|
||||
#include "NativeWrapperDefns.h"
|
||||
|
||||
template<typename T>
|
||||
inline void ScriptInterface::AssignOrToJSVal(const ScriptRequest& rq, JS::MutableHandleValue handle, const T& a)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
|
||||
#include "maths/Fixed.h"
|
||||
@ -44,7 +45,7 @@ class TestScriptConversions : public CxxTest::TestSuite
|
||||
// since they might not be objects. So just use uneval.
|
||||
std::string source;
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", source, v1));
|
||||
TS_ASSERT(ScriptFunction::Call(rq, global, "uneval", source, v1));
|
||||
|
||||
TS_ASSERT_STR_EQUALS(source, expected);
|
||||
}
|
||||
@ -61,7 +62,7 @@ class TestScriptConversions : public CxxTest::TestSuite
|
||||
|
||||
std::string source;
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", source, v1));
|
||||
TS_ASSERT(ScriptFunction::Call(rq, global, "uneval", source, v1));
|
||||
|
||||
if (expected)
|
||||
TS_ASSERT_STR_EQUALS(source, expected);
|
||||
@ -86,12 +87,12 @@ class TestScriptConversions : public CxxTest::TestSuite
|
||||
T r;
|
||||
JS::RootedValue r1(rq.cx);
|
||||
|
||||
TS_ASSERT(script.CallFunction(u1, func.c_str(), r, v1));
|
||||
TS_ASSERT(ScriptFunction::Call(rq, u1, func.c_str(), r, v1));
|
||||
ScriptInterface::ToJSVal(rq, &r1, r);
|
||||
|
||||
std::string source;
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
TS_ASSERT(script.CallFunction(global, "uneval", source, r1));
|
||||
TS_ASSERT(ScriptFunction::Call(rq, global, "uneval", source, r1));
|
||||
|
||||
TS_ASSERT_STR_EQUALS(source, expected);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
#include "lib/self_test.h"
|
||||
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
@ -75,7 +76,7 @@ public:
|
||||
JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1));
|
||||
|
||||
std::string source;
|
||||
TS_ASSERT(script2.CallFunction(obj2, "toSource", source));
|
||||
TS_ASSERT(ScriptFunction::Call(rq2, obj2, "toSource", source));
|
||||
TS_ASSERT_STR_EQUALS(source, "({x:123, y:[1, 1.5, \"2\", \"test\", (void 0), null, true, false]})");
|
||||
}
|
||||
}
|
||||
@ -97,7 +98,7 @@ public:
|
||||
JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1));
|
||||
|
||||
std::string source;
|
||||
TS_ASSERT(script2.CallFunction(obj2, "toSource", source));
|
||||
TS_ASSERT(ScriptFunction::Call(rq2, obj2, "toSource", source));
|
||||
TS_ASSERT_STR_EQUALS(source, "({x:123, y:{w:{z:4}}})");
|
||||
}
|
||||
}
|
||||
@ -153,17 +154,15 @@ public:
|
||||
JS::RootedValue nbrVal(rq.cx, JS::NumberValue(3));
|
||||
int nbr = 0;
|
||||
|
||||
// CallFunctionVoid JS::RootedValue& parameter overload
|
||||
script.CallFunctionVoid(val, "setTo", nbrVal);
|
||||
ScriptFunction::CallVoid(rq, val, "setTo", nbrVal);
|
||||
|
||||
// CallFunction JS::RootedValue* out parameter overload
|
||||
script.CallFunction(val, "inc", &out);
|
||||
// Test that a mutable handle value as return value works.
|
||||
ScriptFunction::Call(rq, val, "inc", &out);
|
||||
|
||||
ScriptInterface::FromJSVal(rq, out, nbr);
|
||||
TS_ASSERT_EQUALS(4, nbr);
|
||||
|
||||
// CallFunction const JS::RootedValue& parameter overload
|
||||
script.CallFunction(val, "add", nbr, nbrVal);
|
||||
ScriptFunction::Call(rq, val, "add", nbr, nbrVal);
|
||||
TS_ASSERT_EQUALS(7, nbr);
|
||||
|
||||
// GetProperty JS::RootedValue* overload
|
||||
@ -187,17 +186,13 @@ public:
|
||||
|
||||
int nbr = 0;
|
||||
|
||||
// CallFunctionVoid JS::HandleValue parameter overload
|
||||
script.CallFunctionVoid(val, "setTo", nbrVal);
|
||||
|
||||
// CallFunction JS::MutableHandleValue out parameter overload
|
||||
script.CallFunction(val, "inc", out);
|
||||
ScriptFunction::CallVoid(rq, val, "setTo", nbrVal);
|
||||
ScriptFunction::Call(rq, val, "inc", out);
|
||||
|
||||
ScriptInterface::FromJSVal(rq, out, nbr);
|
||||
TS_ASSERT_EQUALS(4, nbr);
|
||||
|
||||
// CallFunction const JS::HandleValue& parameter overload
|
||||
script.CallFunction(val, "add", nbr, nbrVal);
|
||||
ScriptFunction::Call(rq, val, "add", nbr, nbrVal);
|
||||
TS_ASSERT_EQUALS(7, nbr);
|
||||
|
||||
// GetProperty JS::MutableHandleValue overload
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "Simulation2.h"
|
||||
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptContext.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
|
||||
@ -726,7 +727,7 @@ void CSimulation2::PreInitGame()
|
||||
{
|
||||
ScriptRequest rq(GetScriptInterface());
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
GetScriptInterface().CallFunctionVoid(global, "PreInitGame");
|
||||
ScriptFunction::CallVoid(rq, global, "PreInitGame");
|
||||
}
|
||||
|
||||
void CSimulation2::InitGame()
|
||||
@ -738,7 +739,7 @@ void CSimulation2::InitGame()
|
||||
JS::RootedValue tmpInitAttributes(rq.cx, GetInitAttributes());
|
||||
GetScriptInterface().GetProperty(tmpInitAttributes, "settings", &settings);
|
||||
|
||||
GetScriptInterface().CallFunctionVoid(global, "InitGame", settings);
|
||||
ScriptFunction::CallVoid(rq, global, "InitGame", settings);
|
||||
}
|
||||
|
||||
void CSimulation2::Update(int turnLength)
|
||||
@ -832,7 +833,7 @@ void CSimulation2::LoadPlayerSettings(bool newPlayers)
|
||||
{
|
||||
ScriptRequest rq(GetScriptInterface());
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
GetScriptInterface().CallFunctionVoid(global, "LoadPlayerSettings", m->m_MapSettings, newPlayers);
|
||||
ScriptFunction::CallVoid(rq, global, "LoadPlayerSettings", m->m_MapSettings, newPlayers);
|
||||
}
|
||||
|
||||
void CSimulation2::LoadMapSettings()
|
||||
@ -842,7 +843,7 @@ void CSimulation2::LoadMapSettings()
|
||||
JS::RootedValue global(rq.cx, rq.globalValue());
|
||||
|
||||
// Initialize here instead of in Update()
|
||||
GetScriptInterface().CallFunctionVoid(global, "LoadMapSettings", m->m_MapSettings);
|
||||
ScriptFunction::CallVoid(rq, global, "LoadMapSettings", m->m_MapSettings);
|
||||
|
||||
GetScriptInterface().FreezeObject(m->m_InitAttributes, true);
|
||||
GetScriptInterface().SetGlobal("InitAttributes", m->m_InitAttributes, true, true, true);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -174,19 +174,22 @@ private:
|
||||
void Run(JS::HandleValue state, int playerID)
|
||||
{
|
||||
m_Commands.clear();
|
||||
m_ScriptInterface->CallFunctionVoid(m_Obj, "HandleMessage", state, playerID);
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
ScriptFunction::CallVoid(rq, m_Obj, "HandleMessage", state, playerID);
|
||||
}
|
||||
// overloaded with a sharedAI part.
|
||||
// javascript can handle both natively on the same function.
|
||||
void Run(JS::HandleValue state, int playerID, JS::HandleValue SharedAI)
|
||||
{
|
||||
m_Commands.clear();
|
||||
m_ScriptInterface->CallFunctionVoid(m_Obj, "HandleMessage", state, playerID, SharedAI);
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
ScriptFunction::CallVoid(rq, m_Obj, "HandleMessage", state, playerID, SharedAI);
|
||||
}
|
||||
void InitAI(JS::HandleValue state, JS::HandleValue SharedAI)
|
||||
{
|
||||
m_Commands.clear();
|
||||
m_ScriptInterface->CallFunctionVoid(m_Obj, "Init", state, m_Player, SharedAI);
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
ScriptFunction::CallVoid(rq, m_Obj, "Init", state, m_Player, SharedAI);
|
||||
}
|
||||
|
||||
CAIWorker& m_Worker;
|
||||
@ -486,7 +489,7 @@ public:
|
||||
{
|
||||
m_ScriptInterface->SetProperty(state, "passabilityMap", m_PassabilityMapVal, true);
|
||||
m_ScriptInterface->SetProperty(state, "territoryMap", m_TerritoryMapVal, true);
|
||||
m_ScriptInterface->CallFunctionVoid(m_SharedAIObj, "init", state);
|
||||
ScriptFunction::CallVoid(rq, m_SharedAIObj, "init", state);
|
||||
|
||||
for (size_t i = 0; i < m_Players.size(); ++i)
|
||||
{
|
||||
@ -792,7 +795,7 @@ private:
|
||||
if (m_HasSharedComponent)
|
||||
{
|
||||
PROFILE3("AI run shared component");
|
||||
m_ScriptInterface->CallFunctionVoid(m_SharedAIObj, "onUpdate", state);
|
||||
ScriptFunction::CallVoid(rq, m_SharedAIObj, "onUpdate", state);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_Players.size(); ++i)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -23,6 +23,7 @@
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/Game.h"
|
||||
#include "ps/Profile.h"
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "simulation2/system/TurnManager.h"
|
||||
|
||||
class CCmpCommandQueue : public ICmpCommandQueue
|
||||
@ -109,14 +110,14 @@ public:
|
||||
|
||||
for (size_t i = 0; i < localCommands.size(); ++i)
|
||||
{
|
||||
bool ok = scriptInterface.CallFunctionVoid(global, "ProcessCommand", localCommands[i].player, localCommands[i].data);
|
||||
bool ok = ScriptFunction::CallVoid(rq, global, "ProcessCommand", localCommands[i].player, localCommands[i].data);
|
||||
if (!ok)
|
||||
LOGERROR("Failed to call ProcessCommand() global script function");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < commands.size(); ++i)
|
||||
{
|
||||
bool ok = scriptInterface.CallFunctionVoid(global, "ProcessCommand", commands[i].player, commands[i].data);
|
||||
bool ok = ScriptFunction::CallVoid(rq, global, "ProcessCommand", commands[i].player, commands[i].data);
|
||||
if (!ok)
|
||||
LOGERROR("Failed to call ProcessCommand() global script function");
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
#include "ScriptComponent.h"
|
||||
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "simulation2/serialization/ISerializer.h"
|
||||
#include "simulation2/serialization/IDeserializer.h"
|
||||
|
||||
@ -29,14 +30,16 @@ CComponentTypeScript::CComponentTypeScript(const ScriptInterface& scriptInterfac
|
||||
|
||||
void CComponentTypeScript::Init(const CParamNode& paramNode, entity_id_t ent)
|
||||
{
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
m_ScriptInterface.SetProperty(m_Instance, "entity", (int)ent, true, false);
|
||||
m_ScriptInterface.SetProperty(m_Instance, "template", paramNode, true, false);
|
||||
m_ScriptInterface.CallFunctionVoid(m_Instance, "Init");
|
||||
ScriptFunction::CallVoid(rq, m_Instance, "Init");
|
||||
}
|
||||
|
||||
void CComponentTypeScript::Deinit()
|
||||
{
|
||||
m_ScriptInterface.CallFunctionVoid(m_Instance, "Deinit");
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
ScriptFunction::CallVoid(rq, m_Instance, "Deinit");
|
||||
}
|
||||
|
||||
void CComponentTypeScript::HandleMessage(const CMessage& msg, bool global)
|
||||
@ -47,7 +50,7 @@ void CComponentTypeScript::HandleMessage(const CMessage& msg, bool global)
|
||||
|
||||
JS::RootedValue msgVal(rq.cx, msg.ToJSValCached(m_ScriptInterface));
|
||||
|
||||
if (!m_ScriptInterface.CallFunctionVoid(m_Instance, name, msgVal))
|
||||
if (!ScriptFunction::CallVoid(rq, m_Instance, name, msgVal))
|
||||
LOGERROR("Script message handler %s failed", name);
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#ifndef INCLUDED_SCRIPTCOMPONENT
|
||||
#define INCLUDED_SCRIPTCOMPONENT
|
||||
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "simulation2/system/Component.h"
|
||||
|
||||
#include "ps/CLogger.h"
|
||||
@ -41,7 +42,8 @@ public:
|
||||
R Call(const char* funcname, const Ts&... params) const
|
||||
{
|
||||
R ret;
|
||||
if (m_ScriptInterface.CallFunction(m_Instance, funcname, ret, params...))
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
if (ScriptFunction::Call(rq, m_Instance, funcname, ret, params...))
|
||||
return ret;
|
||||
LOGERROR("Error calling component script function %s", funcname);
|
||||
return R();
|
||||
@ -51,14 +53,16 @@ public:
|
||||
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...))
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
if (!ScriptFunction::Call(rq, 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...))
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
if (!ScriptFunction::CallVoid(rq, m_Instance, funcname, params...))
|
||||
LOGERROR("Error calling component script function %s", funcname);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "lib/alignment.h"
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "scriptinterface/ScriptExtraHeaders.h"
|
||||
#include "SerializedScriptTypes.h"
|
||||
@ -246,7 +247,7 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
|
||||
if (!protoInfo.hasNullSerialize)
|
||||
{
|
||||
JS::RootedValue data(rq.cx);
|
||||
if (!m_ScriptInterface.CallFunction(val, "Serialize", &data))
|
||||
if (!ScriptFunction::Call(rq, val, "Serialize", &data))
|
||||
throw PSERROR_Serialize_ScriptError("Prototype Serialize function failed");
|
||||
m_Serializer.ScriptVal("data", &data);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
#include "DebugSerializer.h"
|
||||
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
|
||||
#include "lib/secure_crt.h"
|
||||
@ -156,7 +157,7 @@ void CDebugSerializer::PutScriptVal(const char* name, JS::MutableHandleValue val
|
||||
{
|
||||
// If the value has a Serialize property, pretty-parse that instead.
|
||||
// (this gives more accurate OOS reports).
|
||||
m_ScriptInterface.CallFunction(value, "Serialize", &serialize);
|
||||
ScriptFunction::Call(rq, value, "Serialize", &serialize);
|
||||
std::string serialized_source = m_ScriptInterface.ToString(&serialize, true);
|
||||
m_Stream << INDENT << name << ": " << serialized_source << "\n";
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2021 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -22,6 +22,7 @@
|
||||
#include "lib/byte_order.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/CStr.h"
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "scriptinterface/ScriptExtraHeaders.h" // For typed arrays and ArrayBuffer
|
||||
#include "simulation2/serialization/ISerializer.h"
|
||||
@ -180,7 +181,7 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb
|
||||
ScriptVal("data", &data);
|
||||
|
||||
JS::RootedValue objVal(rq.cx, JS::ObjectValue(*obj));
|
||||
m_ScriptInterface.CallFunctionVoid(objVal, "Deserialize", data);
|
||||
ScriptFunction::CallVoid(rq, objVal, "Deserialize", data);
|
||||
|
||||
return JS::ObjectValue(*obj);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "simulation2/serialization/HashSerializer.h"
|
||||
#include "simulation2/serialization/StdSerializer.h"
|
||||
#include "simulation2/serialization/StdDeserializer.h"
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptContext.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
|
||||
@ -333,7 +334,7 @@ public:
|
||||
deserialize2.ScriptVal("script2", &newobj);
|
||||
|
||||
std::string source;
|
||||
TSM_ASSERT(msg, script.CallFunction(newobj, "toSource", source));
|
||||
TSM_ASSERT(msg, ScriptFunction::Call(rq, newobj, "toSource", source));
|
||||
TS_ASSERT_STR_EQUALS(source, expected);
|
||||
}
|
||||
|
||||
@ -867,7 +868,7 @@ public:
|
||||
if (i == 0)
|
||||
{
|
||||
std::string source;
|
||||
TS_ASSERT(script.CallFunction(newobj, "toSource", source));
|
||||
TS_ASSERT(ScriptFunction::Call(rq, newobj, "toSource", source));
|
||||
std::cout << source << "\n";
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user