forked from 0ad/0ad
Makes custom JS objects compatible with SpiderMonkey ESR31.
In v24 you called JS_InitClass and passed in a definition of JSNative functions. Later you could call JS_NewObject with this class and the object would get a prototype with the specified JSNative functions. In ESR31 you now have to explicitly store the prototype object returned by JS_InitClass and pass it as prototype argument to JS_NewObject to achieve the same. This change modifies our existing ScriptInterface implementation for custom object types a bit and uses it at places where the JSAPI was used directly before. Refs #2462 This was SVN commit r15524.
This commit is contained in:
parent
f4949c82ff
commit
1b5ab8142e
@ -518,11 +518,11 @@ JSObject* IGUIObject::GetJSObject()
|
||||
// not have these objects hang around forever using up memory, though.
|
||||
if (m_JSObject.uninitialised())
|
||||
{
|
||||
JSObject* obj = JS_NewObject(cx, &JSI_IGUIObject::JSI_class, NULL, NULL);
|
||||
m_JSObject = CScriptValRooted(cx, OBJECT_TO_JSVAL(obj));
|
||||
JS_SetPrivate(JSVAL_TO_OBJECT(m_JSObject.get()), this);
|
||||
JS::RootedObject obj(cx, m_pGUI->GetScriptInterface()->CreateCustomObject("GUIObject"));
|
||||
m_JSObject = CScriptValRooted(cx, JS::ObjectValue(*obj));
|
||||
JS_SetPrivate(obj, this);
|
||||
}
|
||||
return JSVAL_TO_OBJECT(m_JSObject.get());;
|
||||
return &m_JSObject.get().toObject();
|
||||
}
|
||||
|
||||
CStr IGUIObject::GetPresentableName() const
|
||||
|
@ -51,8 +51,11 @@ JSFunctionSpec JSI_GUISize::JSI_methods[] =
|
||||
|
||||
JSBool JSI_GUISize::construct(JSContext* cx, uint argc, jsval* vp)
|
||||
{
|
||||
JSAutoRequest rq(cx);
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
JSObject* obj = JS_NewObject(cx, &JSI_GUISize::JSI_class, NULL, NULL);
|
||||
|
||||
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
|
||||
JS::RootedObject obj(cx, pScriptInterface->CreateCustomObject("GUISize"));
|
||||
|
||||
if (args.length() == 8)
|
||||
{
|
||||
@ -166,9 +169,12 @@ JSFunctionSpec JSI_GUIColor::JSI_methods[] =
|
||||
|
||||
JSBool JSI_GUIColor::construct(JSContext* cx, uint argc, jsval* vp)
|
||||
{
|
||||
JSAutoRequest rq(cx);
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
JSObject* obj = JS_NewObject(cx, &JSI_GUIColor::JSI_class, NULL, NULL);
|
||||
|
||||
|
||||
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
|
||||
JS::RootedObject obj(cx, pScriptInterface->CreateCustomObject("GUIColor"));
|
||||
|
||||
if (args.length() == 4)
|
||||
{
|
||||
JS_SetProperty(cx, obj, "r", &args[0]);
|
||||
@ -243,7 +249,9 @@ JSBool JSI_GUIMouse::construct(JSContext* cx, uint argc, jsval* vp)
|
||||
{
|
||||
JSAutoRequest rq(cx);
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
JSObject* obj = JS_NewObject(cx, &JSI_GUIMouse::JSI_class, NULL, NULL);
|
||||
|
||||
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
|
||||
JS::RootedObject obj(cx, pScriptInterface->CreateCustomObject("GUIMouse"));
|
||||
|
||||
if (args.length() == 3)
|
||||
{
|
||||
|
@ -56,6 +56,8 @@ JSFunctionSpec JSI_IGUIObject::JSI_methods[] =
|
||||
JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
|
||||
{
|
||||
JSAutoRequest rq(cx);
|
||||
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
|
||||
|
||||
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL);
|
||||
if (!e)
|
||||
return JS_FALSE;
|
||||
@ -161,8 +163,8 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
|
||||
{
|
||||
CColor colour;
|
||||
GUI<CColor>::GetSetting(e, propName, colour);
|
||||
JS::RootedObject obj(cx, JS_NewObject(cx, &JSI_GUIColor::JSI_class, NULL, NULL));
|
||||
vp.set(JS::ObjectValue(*obj));
|
||||
JS::RootedObject obj(cx, pScriptInterface->CreateCustomObject("GUIColor"));
|
||||
vp.setObject(*obj);
|
||||
JS::RootedValue c(cx);
|
||||
// Attempt to minimise ugliness through macrosity
|
||||
#define P(x) c = JS::NumberValue(colour.x); \
|
||||
@ -183,7 +185,8 @@ JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
|
||||
CClientArea area;
|
||||
GUI<CClientArea>::GetSetting(e, propName, area);
|
||||
|
||||
vp.set(JS::ObjectValue(*JS_NewObject(cx, &JSI_GUISize::JSI_class, NULL, NULL)));
|
||||
JS::RootedObject obj(cx, pScriptInterface->CreateCustomObject("GUISize"));
|
||||
vp.setObject(*obj);
|
||||
try
|
||||
{
|
||||
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
|
||||
@ -595,14 +598,17 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
|
||||
|
||||
JSBool JSI_IGUIObject::construct(JSContext* cx, uint argc, jsval* vp)
|
||||
{
|
||||
JSAutoRequest rq(cx);
|
||||
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
|
||||
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
|
||||
|
||||
if (args.length() == 0)
|
||||
{
|
||||
JS_ReportError(cx, "GUIObject has no default constructor");
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JS::RootedObject obj(cx, JS_NewObject(cx, &JSI_IGUIObject::JSI_class, NULL, NULL));
|
||||
JS::RootedObject obj(cx, pScriptInterface->CreateCustomObject("GUIObject"));
|
||||
|
||||
// Store the IGUIObject in the JS object's 'private' area
|
||||
IGUIObject* guiObject = (IGUIObject*)JSVAL_TO_PRIVATE(args[0]);
|
||||
|
@ -946,7 +946,7 @@ void ScriptInterface::DefineCustomObjectType(JSClass *clasp, JSNative constructo
|
||||
|
||||
CustomType type;
|
||||
|
||||
type.m_Object = obj;
|
||||
type.m_Prototype = obj;
|
||||
type.m_Class = clasp;
|
||||
type.m_Constructor = constructor;
|
||||
|
||||
@ -960,12 +960,10 @@ JSObject* ScriptInterface::CreateCustomObject(const std::string & typeName)
|
||||
if (it == m_CustomObjectTypes.end())
|
||||
throw PSERROR_Scripting_TypeDoesNotExist();
|
||||
|
||||
JSFunction* ctor = JS_NewFunction(m->m_cx, (*it).second.m_Constructor, 0, 0,
|
||||
NULL, "ctor_fun");
|
||||
return JS_New(m->m_cx, JS_GetFunctionObject(ctor), 0, NULL);
|
||||
JS::RootedObject prototype(m->m_cx, (*it).second.m_Prototype);
|
||||
return JS_NewObject(m->m_cx, (*it).second.m_Class, prototype, NULL);
|
||||
}
|
||||
|
||||
|
||||
bool ScriptInterface::CallFunctionVoid(jsval val, const char* name)
|
||||
{
|
||||
JSAutoRequest rq(m->m_cx);
|
||||
|
@ -413,8 +413,8 @@ private:
|
||||
class CustomType
|
||||
{
|
||||
public:
|
||||
JSObject * m_Object;
|
||||
JSClass * m_Class;
|
||||
JSObject* m_Prototype;
|
||||
JSClass* m_Class;
|
||||
JSNative m_Constructor;
|
||||
};
|
||||
void Register(const char* name, JSNative fptr, size_t nargs);
|
||||
|
@ -51,8 +51,8 @@ template<> void ScriptInterface::ToJSVal<IComponent*>(JSContext* cx, JS::Value&
|
||||
|
||||
// Otherwise we need to construct a wrapper object
|
||||
// (TODO: cache wrapper objects?)
|
||||
JSClass* cls = val->GetJSClass();
|
||||
if (!cls)
|
||||
JS::RootedObject obj(cx);
|
||||
if (!val->NewJSObject(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface, &obj))
|
||||
{
|
||||
// Report as an error, since scripts really shouldn't try to use unscriptable interfaces
|
||||
LOGERROR(L"IComponent does not have a scriptable interface");
|
||||
@ -60,15 +60,7 @@ template<> void ScriptInterface::ToJSVal<IComponent*>(JSContext* cx, JS::Value&
|
||||
return;
|
||||
}
|
||||
|
||||
JS::RootedObject obj(cx, JS_NewObject(cx, cls, NULL, NULL));
|
||||
if (!obj)
|
||||
{
|
||||
LOGERROR(L"Failed to construct IComponent script object");
|
||||
ret = JS::UndefinedValue();
|
||||
return;
|
||||
}
|
||||
JS_SetPrivate(obj, static_cast<void*>(val));
|
||||
|
||||
ret = JS::ObjectValue(*obj);
|
||||
}
|
||||
|
||||
|
@ -33,9 +33,9 @@ void IComponent::HandleMessage(const CMessage& UNUSED(msg), bool UNUSED(global))
|
||||
{
|
||||
}
|
||||
|
||||
JSClass* IComponent::GetJSClass() const
|
||||
bool IComponent::NewJSObject(ScriptInterface& UNUSED(scriptInterface), JS::MutableHandleObject UNUSED(out)) const
|
||||
{
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
jsval IComponent::GetJSInstance() const
|
||||
|
@ -56,7 +56,11 @@ public:
|
||||
virtual void Serialize(ISerializer& serialize) = 0;
|
||||
virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) = 0;
|
||||
|
||||
virtual JSClass* GetJSClass() const;
|
||||
/**
|
||||
* Returns false by default, indicating that a scripted wrapper of this IComponent is not supported.
|
||||
* Derrived classes should return true if they implement such a wrapper.
|
||||
*/
|
||||
virtual bool NewJSObject(ScriptInterface& scriptInterface, JS::MutableHandleObject out) const;
|
||||
virtual jsval GetJSInstance() const;
|
||||
virtual int GetComponentTypeId() const = 0;
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "simulation2/system/IComponent.h"
|
||||
|
||||
#define DECLARE_INTERFACE_TYPE(iname) \
|
||||
virtual JSClass* GetJSClass() const; \
|
||||
virtual bool NewJSObject(ScriptInterface& scriptInterface, JS::MutableHandleObject out) const; \
|
||||
static void InterfaceInit(ScriptInterface& scriptInterface); \
|
||||
static int GetInterfaceId() { return IID_##iname; }
|
||||
|
||||
|
@ -32,12 +32,13 @@
|
||||
{ NULL } \
|
||||
}; \
|
||||
void ICmp##iname::InterfaceInit(ScriptInterface& scriptInterface) { \
|
||||
JSContext* cx = scriptInterface.GetContext(); \
|
||||
JSAutoRequest rq(cx); \
|
||||
JSObject* global = JS_GetGlobalForScopeChain(cx); \
|
||||
JS_InitClass(cx, global, NULL, &class_ICmp##iname, NULL, 0, NULL, methods_ICmp##iname, NULL, NULL); \
|
||||
scriptInterface.DefineCustomObjectType(&class_ICmp##iname, NULL, 0, NULL, methods_ICmp##iname, NULL, NULL); \
|
||||
} \
|
||||
bool ICmp##iname::NewJSObject(ScriptInterface& scriptInterface, JS::MutableHandleObject out) const\
|
||||
{ \
|
||||
out.set(scriptInterface.CreateCustomObject("ICmp" #iname)); \
|
||||
return true; \
|
||||
} \
|
||||
JSClass* ICmp##iname::GetJSClass() const { return &class_ICmp##iname; } \
|
||||
void RegisterComponentInterface_##iname(ScriptInterface& scriptInterface) { \
|
||||
ICmp##iname::InterfaceInit(scriptInterface); \
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user