Remove all external usage of CmptPrivate. Header cleanup.
This removes usage of CmptPrivate outside of ScriptInterface.
ScriptRequest can now be used to safely recover the scriptInterface from
a JSContext instead of going through ScriptInterface, which allows more
code cleanup.
Follows 34b1920e7b
Differential Revision: https://code.wildfiregames.com/D3963
This was SVN commit r25442.
This commit is contained in:
parent
3ebff376cc
commit
507f44f7f9
@ -163,9 +163,9 @@ bool CMapGeneratorWorker::Run()
|
||||
}
|
||||
|
||||
#define REGISTER_MAPGEN_FUNC(func) \
|
||||
ScriptFunction::Register<&CMapGeneratorWorker::func, ScriptFunction::ObjectFromCBData<CMapGeneratorWorker>>(rq, #func);
|
||||
ScriptFunction::Register<&CMapGeneratorWorker::func, ScriptInterface::ObjectFromCBData<CMapGeneratorWorker>>(rq, #func);
|
||||
#define REGISTER_MAPGEN_FUNC_NAME(func, name) \
|
||||
ScriptFunction::Register<&CMapGeneratorWorker::func, ScriptFunction::ObjectFromCBData<CMapGeneratorWorker>>(rq, name);
|
||||
ScriptFunction::Register<&CMapGeneratorWorker::func, ScriptInterface::ObjectFromCBData<CMapGeneratorWorker>>(rq, name);
|
||||
|
||||
void CMapGeneratorWorker::InitScriptInterface(const u32 seed)
|
||||
{
|
||||
|
@ -85,7 +85,7 @@ size_t CGUIManager::GetPageCount() const
|
||||
return m_PageStack.size();
|
||||
}
|
||||
|
||||
void CGUIManager::SwitchPage(const CStrW& pageName, ScriptInterface* srcScriptInterface, JS::HandleValue initData)
|
||||
void CGUIManager::SwitchPage(const CStrW& pageName, const ScriptInterface* srcScriptInterface, JS::HandleValue initData)
|
||||
{
|
||||
// The page stack is cleared (including the script context where initData came from),
|
||||
// therefore we have to clone initData.
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
/**
|
||||
* Load a new GUI page and make it active. All current pages will be destroyed.
|
||||
*/
|
||||
void SwitchPage(const CStrW& name, ScriptInterface* srcScriptInterface, JS::HandleValue initData);
|
||||
void SwitchPage(const CStrW& name, const ScriptInterface* srcScriptInterface, JS::HandleValue initData);
|
||||
|
||||
/**
|
||||
* Load a new GUI page and make it active. All current pages will be retained,
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "gui/ObjectBases/IGUIObject.h"
|
||||
#include "ps/GameSetup/Config.h"
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "scriptinterface/StructuredClone.h"
|
||||
|
||||
namespace JSI_GUIManager
|
||||
@ -35,9 +36,9 @@ void PushGuiPage(const ScriptRequest& rq, const std::wstring& name, JS::HandleVa
|
||||
g_GUI->PushPage(name, Script::WriteStructuredClone(rq, initData), callbackFunction);
|
||||
}
|
||||
|
||||
void SwitchGuiPage(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& name, JS::HandleValue initData)
|
||||
void SwitchGuiPage(const ScriptInterface& scriptInterface, const std::wstring& name, JS::HandleValue initData)
|
||||
{
|
||||
g_GUI->SwitchPage(name, pCmptPrivate->pScriptInterface, initData);
|
||||
g_GUI->SwitchPage(name, &scriptInterface, initData);
|
||||
}
|
||||
|
||||
void PopGuiPage(const ScriptRequest& rq, JS::HandleValue args)
|
||||
@ -84,8 +85,8 @@ void RegisterScriptFunctions(const ScriptRequest& rq)
|
||||
ScriptFunction::Register<&TemplateExists>(rq, "TemplateExists");
|
||||
ScriptFunction::Register<&GetTemplate>(rq, "GetTemplate");
|
||||
|
||||
ScriptFunction::Register<&CGUI::FindObjectByName, &ScriptFunction::ObjectFromCBData<CGUI>>(rq, "GetGUIObjectByName");
|
||||
ScriptFunction::Register<&CGUI::SetGlobalHotkey, &ScriptFunction::ObjectFromCBData<CGUI>>(rq, "SetGlobalHotkey");
|
||||
ScriptFunction::Register<&CGUI::UnsetGlobalHotkey, &ScriptFunction::ObjectFromCBData<CGUI>>(rq, "UnsetGlobalHotkey");
|
||||
ScriptFunction::Register<&CGUI::FindObjectByName, &ScriptInterface::ObjectFromCBData<CGUI>>(rq, "GetGUIObjectByName");
|
||||
ScriptFunction::Register<&CGUI::SetGlobalHotkey, &ScriptInterface::ObjectFromCBData<CGUI>>(rq, "SetGlobalHotkey");
|
||||
ScriptFunction::Register<&CGUI::UnsetGlobalHotkey, &ScriptInterface::ObjectFromCBData<CGUI>>(rq, "UnsetGlobalHotkey");
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "ps/CLogger.h"
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/ScriptExtraHeaders.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "scriptinterface/ScriptRequest.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -164,8 +164,7 @@ std::unique_ptr<IGUIProxyObject> JSI_GUIProxy<T>::CreateJSObject(const ScriptReq
|
||||
template <typename T>
|
||||
bool JSI_GUIProxy<T>::get(JSContext* cx, JS::HandleObject proxy, JS::HandleValue UNUSED(receiver), JS::HandleId id, JS::MutableHandleValue vp) const
|
||||
{
|
||||
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
|
||||
ScriptRequest rq(*pScriptInterface);
|
||||
ScriptRequest rq(cx);
|
||||
|
||||
T* e = IGUIProxyObject::FromPrivateSlot<T>(proxy.get());
|
||||
if (!e)
|
||||
@ -242,7 +241,7 @@ bool JSI_GUIProxy<T>::set(JSContext* cx, JS::HandleObject proxy, JS::HandleId id
|
||||
return result.fail(JSMSG_OBJECT_REQUIRED);
|
||||
}
|
||||
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
|
||||
ScriptRequest rq(cx);
|
||||
|
||||
JS::RootedValue idval(rq.cx);
|
||||
if (!JS_IdToValue(rq.cx, id, &idval))
|
||||
@ -297,7 +296,7 @@ bool JSI_GUIProxy<T>::delete_(JSContext* cx, JS::HandleObject proxy, JS::HandleI
|
||||
return result.fail(JSMSG_OBJECT_REQUIRED);
|
||||
}
|
||||
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
|
||||
ScriptRequest rq(cx);
|
||||
|
||||
JS::RootedValue idval(rq.cx);
|
||||
if (!JS_IdToValue(rq.cx, id, &idval))
|
||||
|
@ -48,10 +48,10 @@ void JSI_GUISize::RegisterScriptClass(ScriptInterface& scriptInterface)
|
||||
bool JSI_GUISize::construct(JSContext* cx, uint argc, JS::Value* vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
|
||||
ScriptRequest rq(*pScriptInterface);
|
||||
ScriptRequest rq(cx);
|
||||
const ScriptInterface& scriptInterface = rq.GetScriptInterface();
|
||||
|
||||
JS::RootedObject obj(rq.cx, pScriptInterface->CreateCustomObject("GUISize"));
|
||||
JS::RootedObject obj(rq.cx, scriptInterface.CreateCustomObject("GUISize"));
|
||||
|
||||
if (args.length() == 8)
|
||||
{
|
||||
@ -107,8 +107,7 @@ bool JSI_GUISize::toString(JSContext* cx, uint argc, JS::Value* vp)
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
CStr buffer;
|
||||
|
||||
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
|
||||
ScriptRequest rq(*pScriptInterface);
|
||||
ScriptRequest rq(cx);
|
||||
double val, valr;
|
||||
|
||||
#define SIDE(side) \
|
||||
|
@ -144,8 +144,8 @@ bool CGUISize::FromString(const CStr& Value)
|
||||
|
||||
void CGUISize::ToJSVal(const ScriptRequest& rq, JS::MutableHandleValue ret) const
|
||||
{
|
||||
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(rq.cx)->pScriptInterface;
|
||||
ret.setObjectOrNull(pScriptInterface->CreateCustomObject("GUISize"));
|
||||
const ScriptInterface& scriptInterface = rq.GetScriptInterface();
|
||||
ret.setObjectOrNull(scriptInterface.CreateCustomObject("GUISize"));
|
||||
|
||||
if (!ret.isObject())
|
||||
{
|
||||
|
@ -110,11 +110,11 @@ IXmppClient* XmppGetter(const ScriptRequest&, JS::CallArgs&)
|
||||
return g_XmppClient;
|
||||
}
|
||||
|
||||
void SendRegisterGame(ScriptInterface::CmptPrivate* pCmptPrivate, JS::HandleValue data)
|
||||
void SendRegisterGame(const ScriptInterface& scriptInterface, JS::HandleValue data)
|
||||
{
|
||||
if (!g_XmppClient)
|
||||
{
|
||||
ScriptRequest rq(pCmptPrivate->pScriptInterface);
|
||||
ScriptRequest rq(scriptInterface);
|
||||
ScriptException::Raise(rq, "Cannot call SendRegisterGame without an initialized XmppClient!");
|
||||
return;
|
||||
}
|
||||
@ -126,7 +126,7 @@ void SendRegisterGame(ScriptInterface::CmptPrivate* pCmptPrivate, JS::HandleValu
|
||||
return;
|
||||
}
|
||||
|
||||
g_XmppClient->SendIqRegisterGame(*(pCmptPrivate->pScriptInterface), data);
|
||||
g_XmppClient->SendIqRegisterGame(scriptInterface, data);
|
||||
}
|
||||
|
||||
// Unlike other functions, this one just returns Undefined if XmppClient isn't initialised.
|
||||
|
@ -44,8 +44,9 @@
|
||||
#include "ps/UserReport.h"
|
||||
#include "ps/VideoMode.h"
|
||||
#include "scriptinterface/FunctionWrapper.h"
|
||||
#include "scriptinterface/Object.h"
|
||||
#include "scriptinterface/JSON.h"
|
||||
#include "scriptinterface/Object.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
|
||||
#if OS_LINUX
|
||||
#include <fstream>
|
||||
|
@ -24,25 +24,24 @@
|
||||
|
||||
extern void RestartEngine();
|
||||
|
||||
namespace
|
||||
namespace JSI_Mod
|
||||
{
|
||||
bool SetModsAndRestartEngine(ScriptInterface::CmptPrivate* pCmptPrivate, const std::vector<CStr>& mods)
|
||||
bool SetModsAndRestartEngine(const ScriptInterface& scriptInterface, const std::vector<CStr>& mods)
|
||||
{
|
||||
Mod::ClearIncompatibleMods();
|
||||
if (!Mod::CheckAndEnableMods(*(pCmptPrivate->pScriptInterface), mods))
|
||||
if (!Mod::CheckAndEnableMods(scriptInterface, mods))
|
||||
return false;
|
||||
|
||||
RestartEngine();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool HasFailedMods(ScriptInterface::CmptPrivate* UNUSED(pCmptPrivate))
|
||||
bool HasFailedMods()
|
||||
{
|
||||
return Mod::GetFailedMods().size() > 0;
|
||||
}
|
||||
|
||||
void JSI_Mod::RegisterScriptFunctions(const ScriptRequest& rq)
|
||||
void RegisterScriptFunctions(const ScriptRequest& rq)
|
||||
{
|
||||
ScriptFunction::Register<&Mod::GetEngineInfo>(rq, "GetEngineInfo");
|
||||
ScriptFunction::Register<&Mod::GetAvailableMods>(rq, "GetAvailableMods");
|
||||
@ -51,3 +50,4 @@ void JSI_Mod::RegisterScriptFunctions(const ScriptRequest& rq)
|
||||
ScriptFunction::Register<&Mod::GetFailedMods>(rq, "GetFailedMods");
|
||||
ScriptFunction::Register<&SetModsAndRestartEngine>(rq, "SetModsAndRestartEngine");
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,13 @@
|
||||
#include "Object.h"
|
||||
#include "ScriptConversions.h"
|
||||
#include "ScriptExceptions.h"
|
||||
#include "ScriptInterface.h"
|
||||
#include "ScriptRequest.h"
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
class ScriptInterface;
|
||||
|
||||
/**
|
||||
* This class introduces templates to conveniently wrap C++ functions in JSNative functions.
|
||||
* This _is_ rather template heavy, so compilation times beware.
|
||||
@ -128,14 +132,14 @@ private:
|
||||
/**
|
||||
* ConvertFromJS is a wrapper around DoConvertFromJS, and serves to:
|
||||
* - unwrap the tuple types as a parameter pack
|
||||
* - handle specific cases for the first argument (cmptPrivate, ScriptRequest).
|
||||
* - handle specific cases for the first argument (ScriptRequest, ...).
|
||||
*
|
||||
* Trick: to unpack the types of the tuple as a parameter pack, we deduce them from the function signature.
|
||||
* To do that, we want the tuple in the arguments, but we don't want to actually have to default-instantiate,
|
||||
* so we'll pass a nullptr that's static_cast to what we want.
|
||||
*/
|
||||
template<typename ...Types>
|
||||
static std::tuple<Types...> ConvertFromJS(ScriptInterface::CmptPrivate*, const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok, std::tuple<Types...>*)
|
||||
static std::tuple<Types...> ConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok, std::tuple<Types...>*)
|
||||
{
|
||||
if constexpr (sizeof...(Types) == 0)
|
||||
{
|
||||
@ -147,23 +151,9 @@ private:
|
||||
return DoConvertFromJS<0, Types...>(rq, args, went_ok);
|
||||
}
|
||||
|
||||
// Overloads for CmptPrivate* first argument.
|
||||
template<typename ...Types>
|
||||
static std::tuple<ScriptInterface::CmptPrivate*, Types...> ConvertFromJS(ScriptInterface::CmptPrivate* cmptPrivate, const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok, std::tuple<ScriptInterface::CmptPrivate*, Types...>*)
|
||||
{
|
||||
if constexpr (sizeof...(Types) == 0)
|
||||
{
|
||||
// GCC (at least < 9) & VS17 prints warnings if arguments are not used in some constexpr branch.
|
||||
UNUSED2(rq); UNUSED2(args); UNUSED2(went_ok);
|
||||
return std::forward_as_tuple(cmptPrivate);
|
||||
}
|
||||
else
|
||||
return std::tuple_cat(std::forward_as_tuple(cmptPrivate), DoConvertFromJS<0, Types...>(rq, args, went_ok));
|
||||
}
|
||||
|
||||
// Overloads for ScriptRequest& first argument.
|
||||
template<typename ...Types>
|
||||
static std::tuple<const ScriptRequest&, Types...> ConvertFromJS(ScriptInterface::CmptPrivate*, const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok, std::tuple<const ScriptRequest&, Types...>*)
|
||||
static std::tuple<const ScriptRequest&, Types...> ConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok, std::tuple<const ScriptRequest&, Types...>*)
|
||||
{
|
||||
if constexpr (sizeof...(Types) == 0)
|
||||
{
|
||||
@ -177,16 +167,16 @@ private:
|
||||
|
||||
// Overloads for ScriptInterface& first argument.
|
||||
template<typename ...Types>
|
||||
static std::tuple<const ScriptInterface&, Types...> ConvertFromJS(ScriptInterface::CmptPrivate* cmptPrivate, const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok, std::tuple<const ScriptInterface&, Types...>*)
|
||||
static std::tuple<const ScriptInterface&, Types...> ConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& went_ok, std::tuple<const ScriptInterface&, Types...>*)
|
||||
{
|
||||
if constexpr (sizeof...(Types) == 0)
|
||||
{
|
||||
// GCC (at least < 9) & VS17 prints warnings if arguments are not used in some constexpr branch.
|
||||
UNUSED2(rq); UNUSED2(args); UNUSED2(went_ok);
|
||||
return std::forward_as_tuple(*cmptPrivate->pScriptInterface);
|
||||
return std::forward_as_tuple(rq.GetScriptInterface());
|
||||
}
|
||||
else
|
||||
return std::tuple_cat(std::forward_as_tuple(*cmptPrivate->pScriptInterface), DoConvertFromJS<0, Types...>(rq, args, went_ok));
|
||||
return std::tuple_cat(std::forward_as_tuple(rq.GetScriptInterface()), DoConvertFromJS<0, Types...>(rq, args, went_ok));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -289,7 +279,7 @@ public:
|
||||
* so that it can be called from JS and manipulated in Spidermonkey.
|
||||
* Most C++ functions can be directly wrapped, so long as their arguments are
|
||||
* convertible from JS::Value and their return value is convertible to JS::Value (or void)
|
||||
* The C++ function may optionally take const ScriptRequest& or CmptPrivate* as its first argument.
|
||||
* The C++ function may optionally take const ScriptRequest& or ScriptInterface& as its first argument.
|
||||
* The function may be an object method, in which case you need to pass an appropriate getter
|
||||
*
|
||||
* Optimisation note: the ScriptRequest object is created even without arguments,
|
||||
@ -303,8 +293,7 @@ public:
|
||||
using ObjType = typename args_info<decltype(callable)>::object_type;
|
||||
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
ScriptInterface* scriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
|
||||
ScriptRequest rq(*scriptInterface);
|
||||
ScriptRequest rq(cx);
|
||||
|
||||
// If the callable is an object method, we must specify how to fetch the object.
|
||||
static_assert(std::is_same_v<typename args_info<decltype(callable)>::object_type, void> || thisGetter != nullptr,
|
||||
@ -327,7 +316,7 @@ public:
|
||||
#endif
|
||||
|
||||
bool went_ok = true;
|
||||
typename args_info<decltype(callable)>::arg_types outs = ConvertFromJS(ScriptInterface::GetScriptInterfaceAndCBData(cx), rq, args, went_ok, static_cast<typename args_info<decltype(callable)>::arg_types*>(nullptr));
|
||||
typename args_info<decltype(callable)>::arg_types outs = ConvertFromJS(rq, args, went_ok, static_cast<typename args_info<decltype(callable)>::arg_types*>(nullptr));
|
||||
if (!went_ok)
|
||||
return false;
|
||||
|
||||
@ -412,15 +401,6 @@ public:
|
||||
{
|
||||
JS_DefineFunction(cx, scope, name, &ToJSNative<callable, thisGetter>, args_info<decltype(callable)>::nb_args, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the CmptPrivate callback data to T*
|
||||
*/
|
||||
template <typename T>
|
||||
static T* ObjectFromCBData(const ScriptRequest& rq, JS::CallArgs&)
|
||||
{
|
||||
return static_cast<T*>(ScriptInterface::GetScriptInterfaceAndCBData(rq.cx)->pCBData);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // INCLUDED_FUNCTIONWRAPPER
|
||||
|
@ -52,7 +52,6 @@
|
||||
* directly accessing the underlying JS api.
|
||||
*/
|
||||
|
||||
|
||||
struct ScriptInterface_impl
|
||||
{
|
||||
ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptContext>& context);
|
||||
@ -76,14 +75,21 @@ struct ScriptInterface_impl
|
||||
* Constructor for ScriptRequest - here because it needs access into ScriptInterface_impl.
|
||||
*/
|
||||
ScriptRequest::ScriptRequest(const ScriptInterface& scriptInterface) :
|
||||
cx(scriptInterface.m->m_cx), glob(scriptInterface.m->m_glob), nativeScope(scriptInterface.m->m_nativeScope)
|
||||
cx(scriptInterface.m->m_cx),
|
||||
glob(scriptInterface.m->m_glob),
|
||||
nativeScope(scriptInterface.m->m_nativeScope),
|
||||
m_ScriptInterface(scriptInterface)
|
||||
{
|
||||
m_formerRealm = JS::EnterRealm(cx, scriptInterface.m->m_glob);
|
||||
m_FormerRealm = JS::EnterRealm(cx, scriptInterface.m->m_glob);
|
||||
}
|
||||
|
||||
ScriptRequest::~ScriptRequest()
|
||||
{
|
||||
JS::LeaveRealm(cx, m_formerRealm);
|
||||
JS::LeaveRealm(cx, m_FormerRealm);
|
||||
}
|
||||
|
||||
ScriptRequest::ScriptRequest(JSContext* cx) : ScriptRequest(ScriptInterface::CmptPrivate::GetScriptInterface(cx))
|
||||
{
|
||||
}
|
||||
|
||||
JS::Value ScriptRequest::globalValue() const
|
||||
@ -91,6 +97,10 @@ JS::Value ScriptRequest::globalValue() const
|
||||
return JS::ObjectValue(*glob);
|
||||
}
|
||||
|
||||
const ScriptInterface& ScriptRequest::GetScriptInterface() const
|
||||
{
|
||||
return m_ScriptInterface;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -112,7 +122,7 @@ JSClass global_class = {
|
||||
bool print(JSContext* cx, uint argc, JS::Value* vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
|
||||
ScriptRequest rq(cx);
|
||||
|
||||
for (uint i = 0; i < args.length(); ++i)
|
||||
{
|
||||
@ -135,7 +145,7 @@ bool logmsg(JSContext* cx, uint argc, JS::Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
|
||||
ScriptRequest rq(cx);
|
||||
std::wstring str;
|
||||
if (!Script::FromJSVal(rq, args[0], str))
|
||||
return false;
|
||||
@ -153,7 +163,7 @@ bool warn(JSContext* cx, uint argc, JS::Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
|
||||
ScriptRequest rq(cx);
|
||||
std::wstring str;
|
||||
if (!Script::FromJSVal(rq, args[0], str))
|
||||
return false;
|
||||
@ -171,7 +181,7 @@ bool error(JSContext* cx, uint argc, JS::Value* vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
|
||||
ScriptRequest rq(cx);
|
||||
std::wstring str;
|
||||
if (!Script::FromJSVal(rq, args[0], str))
|
||||
return false;
|
||||
@ -271,24 +281,24 @@ static double generate_uniform_real(boost::rand48& rng, double min, double max)
|
||||
}
|
||||
}
|
||||
|
||||
bool Math_random(JSContext* cx, uint argc, JS::Value* vp)
|
||||
{
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
double r;
|
||||
if (!ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface->MathRandom(r))
|
||||
return false;
|
||||
} // anonymous namespace
|
||||
|
||||
args.rval().setNumber(r);
|
||||
bool ScriptInterface::MathRandom(double& nbr) const
|
||||
{
|
||||
if (m->m_rng == nullptr)
|
||||
return false;
|
||||
nbr = generate_uniform_real(*(m->m_rng), 0.0, 1.0);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool ScriptInterface::MathRandom(double& nbr)
|
||||
bool ScriptInterface::Math_random(JSContext* cx, uint argc, JS::Value* vp)
|
||||
{
|
||||
if (m->m_rng == NULL)
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
double r;
|
||||
if (!ScriptInterface::CmptPrivate::GetScriptInterface(cx).MathRandom(r))
|
||||
return false;
|
||||
nbr = generate_uniform_real(*(m->m_rng), 0.0, 1.0);
|
||||
|
||||
args.rval().setNumber(r);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -356,18 +366,30 @@ ScriptInterface::~ScriptInterface()
|
||||
}
|
||||
}
|
||||
|
||||
const ScriptInterface& ScriptInterface::CmptPrivate::GetScriptInterface(JSContext *cx)
|
||||
{
|
||||
CmptPrivate* pCmptPrivate = (CmptPrivate*)JS::GetRealmPrivate(JS::GetCurrentRealmOrNull(cx));
|
||||
ENSURE(pCmptPrivate);
|
||||
return *pCmptPrivate->pScriptInterface;
|
||||
}
|
||||
|
||||
void* ScriptInterface::CmptPrivate::GetCBData(JSContext *cx)
|
||||
{
|
||||
CmptPrivate* pCmptPrivate = (CmptPrivate*)JS::GetRealmPrivate(JS::GetCurrentRealmOrNull(cx));
|
||||
return pCmptPrivate ? pCmptPrivate->pCBData : nullptr;
|
||||
}
|
||||
|
||||
void ScriptInterface::SetCallbackData(void* pCBData)
|
||||
{
|
||||
m_CmptPrivate.pCBData = pCBData;
|
||||
}
|
||||
|
||||
ScriptInterface::CmptPrivate* ScriptInterface::GetScriptInterfaceAndCBData(JSContext* cx)
|
||||
template <>
|
||||
void* ScriptInterface::ObjectFromCBData<void>(const ScriptRequest& rq)
|
||||
{
|
||||
CmptPrivate* pCmptPrivate = (CmptPrivate*)JS::GetRealmPrivate(JS::GetCurrentRealmOrNull(cx));
|
||||
return pCmptPrivate;
|
||||
return ScriptInterface::CmptPrivate::GetCBData(rq.cx);
|
||||
}
|
||||
|
||||
|
||||
bool ScriptInterface::LoadGlobalScripts()
|
||||
{
|
||||
// Ignore this failure in tests
|
||||
|
@ -73,6 +73,7 @@ class ScriptInterface
|
||||
NONCOPYABLE(ScriptInterface);
|
||||
|
||||
friend class ScriptRequest;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -88,12 +89,36 @@ public:
|
||||
|
||||
struct CmptPrivate
|
||||
{
|
||||
friend class ScriptInterface;
|
||||
public:
|
||||
static const ScriptInterface& GetScriptInterface(JSContext* cx);
|
||||
static void* GetCBData(JSContext* cx);
|
||||
protected:
|
||||
ScriptInterface* pScriptInterface; // the ScriptInterface object the compartment belongs to
|
||||
void* pCBData; // meant to be used as the "this" object for callback functions
|
||||
} m_CmptPrivate;
|
||||
};
|
||||
|
||||
void SetCallbackData(void* pCBData);
|
||||
static CmptPrivate* GetScriptInterfaceAndCBData(JSContext* cx);
|
||||
|
||||
/**
|
||||
* Convert the CmptPrivate callback data to T*
|
||||
*/
|
||||
template <typename T>
|
||||
static T* ObjectFromCBData(const ScriptRequest& rq)
|
||||
{
|
||||
static_assert(!std::is_same_v<void, T>);
|
||||
ScriptInterface::CmptPrivate::GetCBData(rq.cx);
|
||||
return static_cast<T*>(ObjectFromCBData<void>(rq));
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant for the function wrapper.
|
||||
*/
|
||||
template <typename T>
|
||||
static T* ObjectFromCBData(const ScriptRequest& rq, JS::CallArgs&)
|
||||
{
|
||||
return ObjectFromCBData<T>(rq);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetGeneralJSContext returns the context without starting a GC request and without
|
||||
@ -177,12 +202,14 @@ public:
|
||||
template<typename T> bool Eval(const char* code, T& out) const;
|
||||
|
||||
/**
|
||||
* MathRandom (this function) calls the random number generator assigned to this ScriptInterface instance and
|
||||
* returns the generated number.
|
||||
* Math_random (with underscore, not this function) is a global function, but different random number generators can be
|
||||
* stored per ScriptInterface. It calls MathRandom of the current ScriptInterface instance.
|
||||
* Calls the random number generator assigned to this ScriptInterface instance and returns the generated number.
|
||||
*/
|
||||
bool MathRandom(double& nbr);
|
||||
bool MathRandom(double& nbr) const;
|
||||
|
||||
/**
|
||||
* JSNative wrapper of the above.
|
||||
*/
|
||||
static bool Math_random(JSContext* cx, uint argc, JS::Value* vp);
|
||||
|
||||
/**
|
||||
* Retrieve the private data field of a JSObject that is an instance of the given JSClass.
|
||||
@ -230,6 +257,8 @@ private:
|
||||
JSNative m_Constructor;
|
||||
};
|
||||
|
||||
CmptPrivate m_CmptPrivate;
|
||||
|
||||
// Take care to keep this declaration before heap rooted members. Destructors of heap rooted
|
||||
// members have to be called before the custom destructor of ScriptInterface_impl.
|
||||
std::unique_ptr<ScriptInterface_impl> m;
|
||||
@ -237,6 +266,10 @@ private:
|
||||
std::map<std::string, CustomType> m_CustomObjectTypes;
|
||||
};
|
||||
|
||||
// Explicitly instantiate void* as that is used for the generic template,
|
||||
// and we want to define it in the .cpp file.
|
||||
template <> void* ScriptInterface::ObjectFromCBData(const ScriptRequest& rq);
|
||||
|
||||
template<typename T>
|
||||
bool ScriptInterface::SetGlobal(const char* name, const T& value, bool replace, bool constant, bool enumerate)
|
||||
{
|
||||
|
@ -71,12 +71,30 @@ public:
|
||||
ScriptRequest(std::shared_ptr<ScriptInterface> scriptInterface) : ScriptRequest(*scriptInterface) {}
|
||||
~ScriptRequest();
|
||||
|
||||
/**
|
||||
* Create a script request from a JSContext.
|
||||
* This can be used to get the script interface in a JSNative function.
|
||||
* In general, you shouldn't have to rely on this otherwise.
|
||||
*/
|
||||
ScriptRequest(JSContext* cx);
|
||||
|
||||
/**
|
||||
* Return the scriptInterface active when creating this ScriptRequest.
|
||||
* Note that this is multi-request safe: even if another ScriptRequest is created,
|
||||
* it will point to the original scriptInterface, and thus can be used to re-enter the realm.
|
||||
*/
|
||||
const ScriptInterface& GetScriptInterface() const;
|
||||
|
||||
JS::Value globalValue() const;
|
||||
|
||||
// Note that JSContext actually changes behind the scenes when creating another ScriptRequest for another realm,
|
||||
// so be _very_ careful when juggling between different realms.
|
||||
JSContext* cx;
|
||||
JS::HandleObject glob;
|
||||
JS::HandleObject nativeScope;
|
||||
private:
|
||||
JS::Realm* m_formerRealm;
|
||||
const ScriptInterface& m_ScriptInterface;
|
||||
JS::Realm* m_FormerRealm;
|
||||
};
|
||||
|
||||
|
||||
|
@ -43,8 +43,8 @@ public:
|
||||
static void _handle(JS::HandleValue) {};
|
||||
static void _handle_2(int, JS::HandleValue, bool) {};
|
||||
|
||||
static void _cmpt_private(ScriptInterface::CmptPrivate*) {};
|
||||
static int _cmpt_private_2(ScriptInterface::CmptPrivate*, int a, bool) { return a; };
|
||||
static void _script_interface(const ScriptInterface&) {};
|
||||
static int _script_interface_2(const ScriptInterface&, int a, bool) { return a; };
|
||||
|
||||
static void _script_request(const ScriptRequest&) {};
|
||||
static int _script_request_2(const ScriptRequest&, int a, bool) { return a; };
|
||||
@ -53,8 +53,8 @@ public:
|
||||
{
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::_handle>), JSNative>);
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::_handle_2>), JSNative>);
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::_cmpt_private>), JSNative>);
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::_cmpt_private_2>), JSNative>);
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::_script_interface>), JSNative>);
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::_script_interface_2>), JSNative>);
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::_script_request>), JSNative>);
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::_script_request_2>), JSNative>);
|
||||
}
|
||||
@ -71,13 +71,13 @@ public:
|
||||
void test_method_wrappers()
|
||||
{
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::test_method::method_1,
|
||||
&ScriptFunction::ObjectFromCBData<test_method>>), JSNative>);
|
||||
&ScriptInterface::ObjectFromCBData<test_method>>), JSNative>);
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::test_method::method_2,
|
||||
&ScriptFunction::ObjectFromCBData<test_method>>), JSNative>);
|
||||
&ScriptInterface::ObjectFromCBData<test_method>>), JSNative>);
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::test_method::const_method_1,
|
||||
&ScriptFunction::ObjectFromCBData<test_method>>), JSNative>);
|
||||
&ScriptInterface::ObjectFromCBData<test_method>>), JSNative>);
|
||||
static_assert(std::is_same_v<decltype(&ScriptFunction::ToJSNative<&TestFunctionWrapper::test_method::const_method_2,
|
||||
&ScriptFunction::ObjectFromCBData<test_method>>), JSNative>);
|
||||
&ScriptInterface::ObjectFromCBData<test_method>>), JSNative>);
|
||||
}
|
||||
|
||||
void test_calling()
|
||||
@ -100,7 +100,7 @@ public:
|
||||
TS_ASSERT_EQUALS(ret, 4);
|
||||
}
|
||||
|
||||
ScriptFunction::Register<&TestFunctionWrapper::_cmpt_private_2>(script, "_cmpt_private_2");
|
||||
ScriptFunction::Register<&TestFunctionWrapper::_script_interface_2>(script, "_cmpt_private_2");
|
||||
{
|
||||
std::string input = "Test._cmpt_private_2(4);";
|
||||
int ret = 0;
|
||||
|
@ -236,7 +236,7 @@ public:
|
||||
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
#define REGISTER_FUNC_NAME(func, name) \
|
||||
ScriptFunction::Register<&CAIWorker::func, ScriptFunction::ObjectFromCBData<CAIWorker>>(rq, name);
|
||||
ScriptFunction::Register<&CAIWorker::func, ScriptInterface::ObjectFromCBData<CAIWorker>>(rq, name);
|
||||
|
||||
REGISTER_FUNC_NAME(PostCommand, "PostCommand");
|
||||
REGISTER_FUNC_NAME(LoadScripts, "IncludeModule");
|
||||
@ -343,7 +343,7 @@ public:
|
||||
/**
|
||||
* Debug function for AI scripts to dump 2D array data (e.g. terrain tile weights).
|
||||
*/
|
||||
void DumpImage(ScriptInterface::CmptPrivate* UNUSED(pCmptPrivate), const std::wstring& name, const std::vector<u32>& data, u32 w, u32 h, u32 max)
|
||||
void DumpImage(const std::wstring& name, const std::vector<u32>& data, u32 w, u32 h, u32 max)
|
||||
{
|
||||
// TODO: this is totally not threadsafe.
|
||||
VfsPath filename = L"screenshots/aidump/" + name;
|
||||
|
@ -49,21 +49,22 @@ public:
|
||||
TSM_ASSERT(L"Running script "+pathname.string(), scriptInterface.LoadScript(pathname, content));
|
||||
}
|
||||
|
||||
static void Script_LoadComponentScript(ScriptInterface::CmptPrivate* pCmptPrivate, const VfsPath& pathname)
|
||||
static void Script_LoadComponentScript(const ScriptInterface& scriptInterface, const VfsPath& pathname)
|
||||
{
|
||||
CComponentManager* componentManager = static_cast<CComponentManager*> (pCmptPrivate->pCBData);
|
||||
ScriptRequest rq(scriptInterface);
|
||||
CComponentManager* componentManager = scriptInterface.ObjectFromCBData<CComponentManager>(rq);
|
||||
TS_ASSERT(componentManager->LoadScript(VfsPath(L"simulation/components") / pathname));
|
||||
}
|
||||
|
||||
static void Script_LoadHelperScript(ScriptInterface::CmptPrivate* pCmptPrivate, const VfsPath& pathname)
|
||||
static void Script_LoadHelperScript(const ScriptInterface& scriptInterface, const VfsPath& pathname)
|
||||
{
|
||||
CComponentManager* componentManager = static_cast<CComponentManager*> (pCmptPrivate->pCBData);
|
||||
ScriptRequest rq(scriptInterface);
|
||||
CComponentManager* componentManager = scriptInterface.ObjectFromCBData<CComponentManager>(rq);
|
||||
TS_ASSERT(componentManager->LoadScript(VfsPath(L"simulation/helpers") / pathname));
|
||||
}
|
||||
|
||||
static JS::Value Script_SerializationRoundTrip(ScriptInterface::CmptPrivate* pCmptPrivate, JS::HandleValue value)
|
||||
static JS::Value Script_SerializationRoundTrip(const ScriptInterface& scriptInterface, JS::HandleValue value)
|
||||
{
|
||||
ScriptInterface& scriptInterface = *(pCmptPrivate->pScriptInterface);
|
||||
ScriptRequest rq(scriptInterface);
|
||||
|
||||
JS::RootedValue val(rq.cx);
|
||||
|
@ -55,7 +55,7 @@ template<> void Script::ToJSVal<IComponent*>(const ScriptRequest& rq, JS::Mutab
|
||||
// Otherwise we need to construct a wrapper object
|
||||
// (TODO: cache wrapper objects?)
|
||||
JS::RootedObject obj(rq.cx);
|
||||
if (!val->NewJSObject(*ScriptInterface::GetScriptInterfaceAndCBData(rq.cx)->pScriptInterface, &obj))
|
||||
if (!val->NewJSObject(rq.GetScriptInterface(), &obj))
|
||||
{
|
||||
// Report as an error, since scripts really shouldn't try to use unscriptable interfaces
|
||||
LOGERROR("IComponent does not have a scriptable interface");
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "scriptinterface/Object.h"
|
||||
#include "scriptinterface/ScriptConversions.h"
|
||||
#include "scriptinterface/ScriptExtraHeaders.h" // For typed arrays and ArrayBuffer
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "simulation2/serialization/ISerializer.h"
|
||||
#include "simulation2/serialization/SerializedScriptTypes.h"
|
||||
#include "simulation2/serialization/StdSerializer.h" // for DEBUG_SERIALIZER_ANNOTATE
|
||||
@ -33,14 +34,14 @@
|
||||
CStdDeserializer::CStdDeserializer(const ScriptInterface& scriptInterface, std::istream& stream) :
|
||||
m_ScriptInterface(scriptInterface), m_Stream(stream)
|
||||
{
|
||||
JS_AddExtraGCRootsTracer(m_ScriptInterface.GetGeneralJSContext(), CStdDeserializer::Trace, this);
|
||||
JS_AddExtraGCRootsTracer(ScriptRequest(scriptInterface).cx, CStdDeserializer::Trace, this);
|
||||
// Insert a dummy object in front, as valid tags start at 1.
|
||||
m_ScriptBackrefs.emplace_back(nullptr);
|
||||
}
|
||||
|
||||
CStdDeserializer::~CStdDeserializer()
|
||||
{
|
||||
JS_RemoveExtraGCRootsTracer(m_ScriptInterface.GetGeneralJSContext(), CStdDeserializer::Trace, this);
|
||||
JS_RemoveExtraGCRootsTracer(ScriptRequest(m_ScriptInterface).cx, CStdDeserializer::Trace, this);
|
||||
}
|
||||
|
||||
void CStdDeserializer::Trace(JSTracer *trc, void *data)
|
||||
|
@ -70,7 +70,7 @@ CComponentManager::CComponentManager(CSimContext& context, shared_ptr<ScriptCont
|
||||
{
|
||||
JSI_VFS::RegisterScriptFunctions_Simulation(m_ScriptInterface);
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
constexpr ScriptFunction::ObjectGetter<CComponentManager> Getter = &ScriptFunction::ObjectFromCBData<CComponentManager>;
|
||||
constexpr ScriptFunction::ObjectGetter<CComponentManager> Getter = &ScriptInterface::ObjectFromCBData<CComponentManager>;
|
||||
ScriptFunction::Register<&CComponentManager::Script_RegisterComponentType, Getter>(rq, "RegisterComponentType");
|
||||
ScriptFunction::Register<&CComponentManager::Script_RegisterSystemComponentType, Getter>(rq, "RegisterSystemComponentType");
|
||||
ScriptFunction::Register<&CComponentManager::Script_ReRegisterComponentType, Getter>(rq, "ReRegisterComponentType");
|
||||
|
Loading…
Reference in New Issue
Block a user