Refactor all usage of RegisterFunction to ScriptFunction::Register

- Replace ScriptInterface::RegisterFunction with
ScriptFunction::Register
 - Mostly removing unused cmpPrivate*
 - Some usage introduces specific getters (mapgenerator, AIWorker,
XmppClient,...)
 - Several passthrough functions are simply removed in favour of calling
the original, reducing duplication
 - Make use of ScriptRequest/ScriptInterface capabilities where
relevant.
- Make JSI_* headers only expose necessary functions, lightening them
considerably and reducing duplication
 - Reuse namespaces in JSI_* implementations directly, reducing visual
noise there

Follows f3aedf88a6

Differential Revision: https://code.wildfiregames.com/D3626
This was SVN commit r24983.
This commit is contained in:
wraitii
2021-03-02 20:01:14 +00:00
parent 869076ebc5
commit cb346e207b
52 changed files with 820 additions and 1969 deletions
@@ -56,16 +56,6 @@ template <typename T> struct MaybeRef;
#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"
// Define RegisterFunction<TR, T0..., f>
#define OVERLOADS(z, i, data) \
template <typename R, TYPENAME_T0_HEAD(z,i) R (*fptr) ( ScriptInterface::CmptPrivate* T0_TAIL_MAYBE_REF(z,i) )> \
void RegisterFunction(const char* name) const \
{ \
Register(name, call<R T0_TAIL(z,i), fptr>, nargs<T0(z,i)>()); \
}
BOOST_PP_REPEAT(SCRIPT_INTERFACE_MAX_ARGS, OVERLOADS, ~)
#undef OVERLOADS
// 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) \
+43 -84
View File
@@ -17,6 +17,7 @@
#include "precompiled.h"
#include "FunctionWrapper.h"
#include "ScriptContext.h"
#include "ScriptExtraHeaders.h"
#include "ScriptInterface.h"
@@ -55,7 +56,6 @@ struct ScriptInterface_impl
{
ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptContext>& context);
~ScriptInterface_impl();
void Register(const char* name, JSNative fptr, uint nargs) const;
// Take care to keep this declaration before heap rooted members. Destructors of heap rooted
// members have to be called before the context destructor.
@@ -176,107 +176,77 @@ bool error(JSContext* cx, uint argc, JS::Value* vp)
return true;
}
bool deepcopy(JSContext* cx, uint argc, JS::Value* vp)
JS::Value deepcopy(const ScriptRequest& rq, JS::HandleValue val)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
if (args.length() < 1)
if (val.isNullOrUndefined())
{
args.rval().setUndefined();
return true;
ScriptException::Raise(rq, "deepcopy requires one argument.");
return JS::UndefinedValue();
}
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
JS::RootedValue ret(cx);
if (!JS_StructuredClone(rq.cx, args[0], &ret, NULL, NULL))
return false;
args.rval().set(ret);
return true;
JS::RootedValue ret(rq.cx);
if (!JS_StructuredClone(rq.cx, val, &ret, NULL, NULL))
{
ScriptException::Raise(rq, "deepcopy StructureClone copy failed.");
return JS::UndefinedValue();
}
return ret;
}
bool deepfreeze(JSContext* cx, uint argc, JS::Value* vp)
JS::Value deepfreeze(const ScriptInterface& scriptInterface, JS::HandleValue val)
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
if (args.length() != 1 || !args.get(0).isObject())
ScriptRequest rq(scriptInterface);
if (!val.isObject())
{
ScriptException::Raise(rq, "deepfreeze requires exactly one object as an argument.");
return false;
return JS::UndefinedValue();
}
ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface->FreezeObject(args.get(0), true);
args.rval().set(args.get(0));
return true;
scriptInterface.FreezeObject(val, true);
return val;
}
bool ProfileStart(JSContext* cx, uint argc, JS::Value* vp)
void ProfileStart(const std::string& regionName)
{
const char* name = "(ProfileStart)";
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
if (args.length() >= 1)
{
std::string str;
if (!ScriptInterface::FromJSVal(rq, args[0], str))
return false;
typedef boost::flyweight<
std::string,
boost::flyweights::no_tracking,
boost::flyweights::no_locking
> StringFlyweight;
typedef boost::flyweight<
std::string,
boost::flyweights::no_tracking,
boost::flyweights::no_locking
> StringFlyweight;
name = StringFlyweight(str).get().c_str();
}
if (!regionName.empty())
name = StringFlyweight(regionName).get().c_str();
if (CProfileManager::IsInitialised() && Threading::IsMainThread())
g_Profiler.StartScript(name);
g_Profiler2.RecordRegionEnter(name);
args.rval().setUndefined();
return true;
}
bool ProfileStop(JSContext* UNUSED(cx), uint argc, JS::Value* vp)
void ProfileStop()
{
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
if (CProfileManager::IsInitialised() && Threading::IsMainThread())
g_Profiler.Stop();
g_Profiler2.RecordRegionLeave();
args.rval().setUndefined();
return true;
}
bool ProfileAttribute(JSContext* cx, uint argc, JS::Value* vp)
void ProfileAttribute(const std::string& attr)
{
const char* name = "(ProfileAttribute)";
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); \
if (args.length() >= 1)
{
std::string str;
if (!ScriptInterface::FromJSVal(rq, args[0], str))
return false;
typedef boost::flyweight<
std::string,
boost::flyweights::no_tracking,
boost::flyweights::no_locking
> StringFlyweight;
typedef boost::flyweight<
std::string,
boost::flyweights::no_tracking,
boost::flyweights::no_locking
> StringFlyweight;
name = StringFlyweight(str).get().c_str();
}
if (!attr.empty())
name = StringFlyweight(attr).get().c_str();
g_Profiler2.RecordAttribute("%s", name);
args.rval().setUndefined();
return true;
}
// Math override functions:
@@ -336,18 +306,19 @@ ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const sh
JS_DefineProperty(m_cx, m_glob, "global", m_glob, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
m_nativeScope = JS_DefineObject(m_cx, m_glob, nativeScopeName, nullptr, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
// These first 4 actually use CallArgs & thus don't use ScriptFunction
JS_DefineFunction(m_cx, m_glob, "print", ::print, 0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(m_cx, m_glob, "log", ::logmsg, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(m_cx, m_glob, "warn", ::warn, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(m_cx, m_glob, "error", ::error, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(m_cx, m_glob, "clone", ::deepcopy, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
JS_DefineFunction(m_cx, m_glob, "deepfreeze", ::deepfreeze, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
ScriptFunction::Register<deepcopy>(m_cx, m_glob, "clone");
ScriptFunction::Register<deepfreeze>(m_cx, m_glob, "deepfreeze");
Register("ProfileStart", ::ProfileStart, 1);
Register("ProfileStop", ::ProfileStop, 0);
Register("ProfileAttribute", ::ProfileAttribute, 1);
m_nativeScope = JS_DefineObject(m_cx, m_glob, nativeScopeName, nullptr, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
ScriptFunction::Register<&ProfileStart>(m_cx, m_nativeScope, "ProfileStart");
ScriptFunction::Register<&ProfileStop>(m_cx, m_nativeScope, "ProfileStop");
ScriptFunction::Register<&ProfileAttribute>(m_cx, m_nativeScope, "ProfileAttribute");
m_context->RegisterRealm(JS::GetObjectRealmOrNull(m_glob));
}
@@ -357,13 +328,6 @@ ScriptInterface_impl::~ScriptInterface_impl()
m_context->UnRegisterRealm(JS::GetObjectRealmOrNull(m_glob));
}
void ScriptInterface_impl::Register(const char* name, JSNative fptr, uint nargs) const
{
JSAutoRealm autoRealm(m_cx, m_glob);
JS::RootedObject nativeScope(m_cx, m_nativeScope);
JS::RootedFunction func(m_cx, JS_DefineFunction(m_cx, nativeScope, name, fptr, nargs, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT));
}
ScriptInterface::ScriptInterface(const char* nativeScopeName, const char* debugName, const shared_ptr<ScriptContext>& context) :
m(std::make_unique<ScriptInterface_impl>(nativeScopeName, context))
{
@@ -441,11 +405,6 @@ bool ScriptInterface::ReplaceNondeterministicRNG(boost::rand48& rng)
return false;
}
void ScriptInterface::Register(const char* name, JSNative fptr, size_t nargs) const
{
m->Register(name, fptr, (uint)nargs);
}
JSContext* ScriptInterface::GetGeneralJSContext() const
{
return m->m_context->GetGeneralJSContext();
+1 -6
View File
@@ -34,7 +34,6 @@ ERROR_TYPE(Scripting_LoadFile, OpenFailed);
ERROR_TYPE(Scripting_LoadFile, EvalErrors);
ERROR_TYPE(Scripting, CallFunctionFailed);
ERROR_TYPE(Scripting, RegisterFunctionFailed);
ERROR_TYPE(Scripting, DefineConstantFailed);
ERROR_TYPE(Scripting, CreateObjectFailed);
ERROR_TYPE(Scripting, TypeDoesNotExist);
@@ -105,7 +104,7 @@ public:
/**
* Constructor.
* @param nativeScopeName Name of global object that functions (via RegisterFunction) will
* @param nativeScopeName Name of global object that functions (via ScriptFunction::Register) will
* be placed into, as a scoping mechanism; typically "Engine"
* @param debugName Name of this interface for CScriptStats purposes.
* @param context ScriptContext to use when initializing this interface.
@@ -455,7 +454,6 @@ private:
JSClass* m_Class;
JSNative m_Constructor;
};
void Register(const char* name, JSNative fptr, size_t nargs) const;
// 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.
@@ -470,9 +468,6 @@ public:
// This declares:
//
// template <R, T0..., TR (*fptr) (void* cbdata, T0...)>
// void RegisterFunction(const char* functionName) const;
//
// template <R, T0..., TR (*fptr) (void* cbdata, T0...)>
// static JSNative call;
//
// template <R, T0..., JSClass*, TC, TR (TC:*fptr) (T0...)>