Wrap JSAutoRequest and replace usage of JSContext* with the wrapper.

JSAutoRequest is required before calling into most JSAPI methods, for GC
reasons.
Calling it is required and fragile as one must not forget.
Further, SM52 and later make manipulating JSContext* dangerous as that
can cross Compartment(Realm in SM68) barriers (and ScriptInterface now
matches a Compartment).

The solution to both problems is to avoid using JSContext* in 0 A.D.
itself. To achieve this, a Request class is introduced, and must be used
to access a JSContext* from a scriptInterface. Further, Request is
passed to other ScriptInterface functions isntead of JSContext*, making
it obvious that the caller has already called it, reducing errors and
redundant JSAutoRequest calls.
Only JSNative functions now get a naked JSContext* without protection,
but the likelihood of forgetting a request is lower since many
ScriptInterface functions now expect it.

JSContext* is directly passed to JSAPI functions only.

Part of the SM52 migration, stage: SM45 compatible

Based on a patch by: Itms
Tested By: Freagarach
Refs #4893

Differential Revision: https://code.wildfiregames.com/D3088
This was SVN commit r24176.
This commit is contained in:
wraitii
2020-11-13 13:18:22 +00:00
parent 6a029d2a84
commit ee0d204bf6
74 changed files with 1591 additions and 1812 deletions
+60 -71
View File
@@ -29,13 +29,12 @@
#include <string>
#define SET(obj, name, value) STMT(JS::RootedValue v_(cx); AssignOrToJSVal(cx, &v_, (value)); JS_SetProperty(cx, obj, (name), v_))
#define SET(obj, name, value) STMT(JS::RootedValue v_(rq.cx); AssignOrToJSVal(rq, &v_, (value)); JS_SetProperty(rq.cx, obj, (name), v_))
// ignore JS_SetProperty return value, because errors should be impossible
// and we can't do anything useful in the case of errors anyway
template<> void ScriptInterface::ToJSVal<SDL_Event_>(JSContext* cx, JS::MutableHandleValue ret, SDL_Event_ const& val)
template<> void ScriptInterface::ToJSVal<SDL_Event_>(const Request& rq, JS::MutableHandleValue ret, SDL_Event_ const& val)
{
JSAutoRequest rq(cx);
const char* typeName;
switch (val.ev.type)
@@ -52,7 +51,7 @@ template<> void ScriptInterface::ToJSVal<SDL_Event_>(JSContext* cx, JS::MutableH
default: typeName = "(unknown)"; break;
}
JS::RootedObject obj(cx, JS_NewPlainObject(cx));
JS::RootedObject obj(rq.cx, JS_NewPlainObject(rq.cx));
if (!obj)
{
ret.setUndefined();
@@ -69,14 +68,14 @@ template<> void ScriptInterface::ToJSVal<SDL_Event_>(JSContext* cx, JS::MutableH
// SET(obj, "which", (int)val.ev.key.which); // (not in wsdl.h)
// SET(obj, "state", (int)val.ev.key.state); // (not in wsdl.h)
JS::RootedObject keysym(cx, JS_NewPlainObject(cx));
JS::RootedObject keysym(rq.cx, JS_NewPlainObject(rq.cx));
if (!keysym)
{
ret.setUndefined();
return;
}
JS::RootedValue keysymVal(cx, JS::ObjectValue(*keysym));
JS_SetProperty(cx, obj, "keysym", keysymVal);
JS::RootedValue keysymVal(rq.cx, JS::ObjectValue(*keysym));
JS_SetProperty(rq.cx, obj, "keysym", keysymVal);
// SET(keysym, "scancode", (int)val.ev.key.keysym.scancode); // (not in wsdl.h)
SET(keysym, "sym", (int)val.ev.key.keysym.sym);
@@ -121,7 +120,7 @@ template<> void ScriptInterface::ToJSVal<SDL_Event_>(JSContext* cx, JS::MutableH
ret.setObject(*obj);
}
template<> void ScriptInterface::ToJSVal<IGUIObject*>(JSContext* UNUSED(cx), JS::MutableHandleValue ret, IGUIObject* const& val)
template<> void ScriptInterface::ToJSVal<IGUIObject*>(const Request& UNUSED(rq), JS::MutableHandleValue ret, IGUIObject* const& val)
{
if (val == nullptr)
ret.setNull();
@@ -129,15 +128,15 @@ template<> void ScriptInterface::ToJSVal<IGUIObject*>(JSContext* UNUSED(cx), JS:
ret.setObject(*val->GetJSObject());
}
template<> void ScriptInterface::ToJSVal<CGUIString>(JSContext* cx, JS::MutableHandleValue ret, const CGUIString& val)
template<> void ScriptInterface::ToJSVal<CGUIString>(const Request& rq, JS::MutableHandleValue ret, const CGUIString& val)
{
ScriptInterface::ToJSVal(cx, ret, val.GetOriginalString());
ScriptInterface::ToJSVal(rq, ret, val.GetOriginalString());
}
template<> bool ScriptInterface::FromJSVal<CGUIString>(JSContext* cx, JS::HandleValue v, CGUIString& out)
template<> bool ScriptInterface::FromJSVal<CGUIString>(const Request& rq, JS::HandleValue v, CGUIString& out)
{
std::wstring val;
if (!FromJSVal(cx, v, val))
if (!FromJSVal(rq, v, val))
return false;
out.SetValue(val);
return true;
@@ -147,82 +146,76 @@ JSVAL_VECTOR(CVector2D)
JSVAL_VECTOR(std::vector<CVector2D>)
JSVAL_VECTOR(CGUIString)
template<> void ScriptInterface::ToJSVal<CGUIColor>(JSContext* cx, JS::MutableHandleValue ret, const CGUIColor& val)
template<> void ScriptInterface::ToJSVal<CGUIColor>(const Request& rq, JS::MutableHandleValue ret, const CGUIColor& val)
{
ToJSVal<CColor>(cx, ret, val);
ToJSVal<CColor>(rq, ret, val);
}
/**
* The color depends on the predefined color database stored in the current GUI page.
*/
template<> bool ScriptInterface::FromJSVal<CGUIColor>(JSContext* cx, JS::HandleValue v, CGUIColor& out) = delete;
template<> bool ScriptInterface::FromJSVal<CGUIColor>(const Request& rq, JS::HandleValue v, CGUIColor& out) = delete;
template<> void ScriptInterface::ToJSVal<CSize>(JSContext* cx, JS::MutableHandleValue ret, const CSize& val)
template<> void ScriptInterface::ToJSVal<CSize>(const Request& rq, JS::MutableHandleValue ret, const CSize& val)
{
CreateObject(cx, ret, "width", val.cx, "height", val.cy);
CreateObject(rq, ret, "width", val.cx, "height", val.cy);
}
template<> bool ScriptInterface::FromJSVal<CSize>(JSContext* cx, JS::HandleValue v, CSize& out)
template<> bool ScriptInterface::FromJSVal<CSize>(const Request& rq, JS::HandleValue v, CSize& out)
{
if (!v.isObject())
{
JSAutoRequest rq(cx);
JS_ReportError(cx, "CSize value must be an object!");
JS_ReportError(rq.cx, "CSize value must be an object!");
return false;
}
if (!FromJSProperty(cx, v, "width", out.cx))
if (!FromJSProperty(rq, v, "width", out.cx))
{
JSAutoRequest rq(cx);
JS_ReportError(cx, "Failed to get CSize.cx property");
JS_ReportError(rq.cx, "Failed to get CSize.cx property");
return false;
}
if (!FromJSProperty(cx, v, "height", out.cy))
if (!FromJSProperty(rq, v, "height", out.cy))
{
JSAutoRequest rq(cx);
JS_ReportError(cx, "Failed to get CSize.cy property");
JS_ReportError(rq.cx, "Failed to get CSize.cy property");
return false;
}
return true;
}
template<> void ScriptInterface::ToJSVal<CPos>(JSContext* cx, JS::MutableHandleValue ret, const CPos& val)
template<> void ScriptInterface::ToJSVal<CPos>(const Request& rq, JS::MutableHandleValue ret, const CPos& val)
{
CreateObject(cx, ret, "x", val.x, "y", val.y);
CreateObject(rq, ret, "x", val.x, "y", val.y);
}
template<> bool ScriptInterface::FromJSVal<CPos>(JSContext* cx, JS::HandleValue v, CPos& out)
template<> bool ScriptInterface::FromJSVal<CPos>(const Request& rq, JS::HandleValue v, CPos& out)
{
if (!v.isObject())
{
JSAutoRequest rq(cx);
JS_ReportError(cx, "CPos value must be an object!");
JS_ReportError(rq.cx, "CPos value must be an object!");
return false;
}
if (!FromJSProperty(cx, v, "x", out.x))
if (!FromJSProperty(rq, v, "x", out.x))
{
JSAutoRequest rq(cx);
JS_ReportError(cx, "Failed to get CPos.x property");
JS_ReportError(rq.cx, "Failed to get CPos.x property");
return false;
}
if (!FromJSProperty(cx, v, "y", out.y))
if (!FromJSProperty(rq, v, "y", out.y))
{
JSAutoRequest rq(cx);
JS_ReportError(cx, "Failed to get CPos.y property");
JS_ReportError(rq.cx, "Failed to get CPos.y property");
return false;
}
return true;
}
template<> void ScriptInterface::ToJSVal<CRect>(JSContext* cx, JS::MutableHandleValue ret, const CRect& val)
template<> void ScriptInterface::ToJSVal<CRect>(const Request& rq, JS::MutableHandleValue ret, const CRect& val)
{
CreateObject(
cx,
rq,
ret,
"left", val.left,
"right", val.right,
@@ -230,37 +223,37 @@ template<> void ScriptInterface::ToJSVal<CRect>(JSContext* cx, JS::MutableHandle
"bottom", val.bottom);
}
template<> void ScriptInterface::ToJSVal<CGUISize>(JSContext* cx, JS::MutableHandleValue ret, const CGUISize& val)
template<> void ScriptInterface::ToJSVal<CGUISize>(const Request& rq, JS::MutableHandleValue ret, const CGUISize& val)
{
val.ToJSVal(cx, ret);
val.ToJSVal(rq, ret);
}
template<> bool ScriptInterface::FromJSVal<CGUISize>(JSContext* cx, JS::HandleValue v, CGUISize& out)
template<> bool ScriptInterface::FromJSVal<CGUISize>(const Request& rq, JS::HandleValue v, CGUISize& out)
{
return out.FromJSVal(cx, v);
return out.FromJSVal(rq, v);
}
template<> void ScriptInterface::ToJSVal<CGUIList>(JSContext* cx, JS::MutableHandleValue ret, const CGUIList& val)
template<> void ScriptInterface::ToJSVal<CGUIList>(const Request& rq, JS::MutableHandleValue ret, const CGUIList& val)
{
ToJSVal(cx, ret, val.m_Items);
ToJSVal(rq, ret, val.m_Items);
}
template<> bool ScriptInterface::FromJSVal<CGUIList>(JSContext* cx, JS::HandleValue v, CGUIList& out)
template<> bool ScriptInterface::FromJSVal<CGUIList>(const Request& rq, JS::HandleValue v, CGUIList& out)
{
return FromJSVal(cx, v, out.m_Items);
return FromJSVal(rq, v, out.m_Items);
}
template<> void ScriptInterface::ToJSVal<CGUISeries>(JSContext* cx, JS::MutableHandleValue ret, const CGUISeries& val)
template<> void ScriptInterface::ToJSVal<CGUISeries>(const Request& rq, JS::MutableHandleValue ret, const CGUISeries& val)
{
ToJSVal(cx, ret, val.m_Series);
ToJSVal(rq, ret, val.m_Series);
}
template<> bool ScriptInterface::FromJSVal<CGUISeries>(JSContext* cx, JS::HandleValue v, CGUISeries& out)
template<> bool ScriptInterface::FromJSVal<CGUISeries>(const Request& rq, JS::HandleValue v, CGUISeries& out)
{
return FromJSVal(cx, v, out.m_Series);
return FromJSVal(rq, v, out.m_Series);
}
template<> void ScriptInterface::ToJSVal<EVAlign>(JSContext* cx, JS::MutableHandleValue ret, const EVAlign& val)
template<> void ScriptInterface::ToJSVal<EVAlign>(const Request& rq, JS::MutableHandleValue ret, const EVAlign& val)
{
std::string word;
switch (val)
@@ -279,17 +272,16 @@ template<> void ScriptInterface::ToJSVal<EVAlign>(JSContext* cx, JS::MutableHand
default:
word = "error";
JSAutoRequest rq(cx);
JS_ReportError(cx, "Invalid EVAlign");
JS_ReportError(rq.cx, "Invalid EVAlign");
break;
}
ToJSVal(cx, ret, word);
ToJSVal(rq, ret, word);
}
template<> bool ScriptInterface::FromJSVal<EVAlign>(JSContext* cx, JS::HandleValue v, EVAlign& out)
template<> bool ScriptInterface::FromJSVal<EVAlign>(const Request& rq, JS::HandleValue v, EVAlign& out)
{
std::string word;
FromJSVal(cx, v, word);
FromJSVal(rq, v, word);
if (word == "top")
out = EVAlign_Top;
@@ -300,14 +292,13 @@ template<> bool ScriptInterface::FromJSVal<EVAlign>(JSContext* cx, JS::HandleVal
else
{
out = EVAlign_Top;
JSAutoRequest rq(cx);
JS_ReportError(cx, "Invalid alignment (should be 'left', 'right' or 'center')");
JS_ReportError(rq.cx, "Invalid alignment (should be 'left', 'right' or 'center')");
return false;
}
return true;
}
template<> void ScriptInterface::ToJSVal<EAlign>(JSContext* cx, JS::MutableHandleValue ret, const EAlign& val)
template<> void ScriptInterface::ToJSVal<EAlign>(const Request& rq, JS::MutableHandleValue ret, const EAlign& val)
{
std::string word;
switch (val)
@@ -323,17 +314,16 @@ template<> void ScriptInterface::ToJSVal<EAlign>(JSContext* cx, JS::MutableHandl
break;
default:
word = "error";
JSAutoRequest rq(cx);
JS_ReportError(cx, "Invalid alignment (should be 'left', 'right' or 'center')");
JS_ReportError(rq.cx, "Invalid alignment (should be 'left', 'right' or 'center')");
break;
}
ToJSVal(cx, ret, word);
ToJSVal(rq, ret, word);
}
template<> bool ScriptInterface::FromJSVal<EAlign>(JSContext* cx, JS::HandleValue v, EAlign& out)
template<> bool ScriptInterface::FromJSVal<EAlign>(const Request& rq, JS::HandleValue v, EAlign& out)
{
std::string word;
FromJSVal(cx, v, word);
FromJSVal(rq, v, word);
if (word == "left")
out = EAlign_Left;
@@ -344,22 +334,21 @@ template<> bool ScriptInterface::FromJSVal<EAlign>(JSContext* cx, JS::HandleValu
else
{
out = EAlign_Left;
JSAutoRequest rq(cx);
JS_ReportError(cx, "Invalid alignment (should be 'left', 'right' or 'center')");
JS_ReportError(rq.cx, "Invalid alignment (should be 'left', 'right' or 'center')");
return false;
}
return true;
}
template<> void ScriptInterface::ToJSVal<CGUISpriteInstance>(JSContext* cx, JS::MutableHandleValue ret, const CGUISpriteInstance& val)
template<> void ScriptInterface::ToJSVal<CGUISpriteInstance>(const Request& rq, JS::MutableHandleValue ret, const CGUISpriteInstance& val)
{
ToJSVal(cx, ret, val.GetName());
ToJSVal(rq, ret, val.GetName());
}
template<> bool ScriptInterface::FromJSVal<CGUISpriteInstance>(JSContext* cx, JS::HandleValue v, CGUISpriteInstance& out)
template<> bool ScriptInterface::FromJSVal<CGUISpriteInstance>(const Request& rq, JS::HandleValue v, CGUISpriteInstance& out)
{
std::string name;
if (!FromJSVal(cx, v, name))
if (!FromJSVal(rq, v, name))
return false;
out.SetName(name);
@@ -41,9 +41,8 @@ void JSI_GUIManager::PopGuiPage(ScriptInterface::CxPrivate* pCxPrivate, JS::Hand
{
if (g_GUI->GetPageCount() < 2)
{
JSContext* cx = pCxPrivate->pScriptInterface->GetContext();
JSAutoRequest rq(cx);
JS_ReportError(cx, "Can't pop GUI pages when less than two pages are opened!");
ScriptInterface::Request rq(pCxPrivate);
JS_ReportError(rq.cx, "Can't pop GUI pages when less than two pages are opened!");
return;
}
+31 -30
View File
@@ -43,45 +43,46 @@ void JSI_GUISize::RegisterScriptClass(ScriptInterface& scriptInterface)
bool JSI_GUISize::construct(JSContext* cx, uint argc, JS::Value* vp)
{
JSAutoRequest rq(cx);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
JS::RootedObject obj(cx, pScriptInterface->CreateCustomObject("GUISize"));
ScriptInterface::Request rq(*pScriptInterface);
JS::RootedObject obj(rq.cx, pScriptInterface->CreateCustomObject("GUISize"));
if (args.length() == 8)
{
JS_SetProperty(cx, obj, "left", args[0]);
JS_SetProperty(cx, obj, "top", args[1]);
JS_SetProperty(cx, obj, "right", args[2]);
JS_SetProperty(cx, obj, "bottom", args[3]);
JS_SetProperty(cx, obj, "rleft", args[4]);
JS_SetProperty(cx, obj, "rtop", args[5]);
JS_SetProperty(cx, obj, "rright", args[6]);
JS_SetProperty(cx, obj, "rbottom", args[7]);
JS_SetProperty(rq.cx, obj, "left", args[0]);
JS_SetProperty(rq.cx, obj, "top", args[1]);
JS_SetProperty(rq.cx, obj, "right", args[2]);
JS_SetProperty(rq.cx, obj, "bottom", args[3]);
JS_SetProperty(rq.cx, obj, "rleft", args[4]);
JS_SetProperty(rq.cx, obj, "rtop", args[5]);
JS_SetProperty(rq.cx, obj, "rright", args[6]);
JS_SetProperty(rq.cx, obj, "rbottom", args[7]);
}
else if (args.length() == 4)
{
JS::RootedValue zero(cx, JS::NumberValue(0));
JS_SetProperty(cx, obj, "left", args[0]);
JS_SetProperty(cx, obj, "top", args[1]);
JS_SetProperty(cx, obj, "right", args[2]);
JS_SetProperty(cx, obj, "bottom", args[3]);
JS_SetProperty(cx, obj, "rleft", zero);
JS_SetProperty(cx, obj, "rtop", zero);
JS_SetProperty(cx, obj, "rright", zero);
JS_SetProperty(cx, obj, "rbottom", zero);
JS::RootedValue zero(rq.cx, JS::NumberValue(0));
JS_SetProperty(rq.cx, obj, "left", args[0]);
JS_SetProperty(rq.cx, obj, "top", args[1]);
JS_SetProperty(rq.cx, obj, "right", args[2]);
JS_SetProperty(rq.cx, obj, "bottom", args[3]);
JS_SetProperty(rq.cx, obj, "rleft", zero);
JS_SetProperty(rq.cx, obj, "rtop", zero);
JS_SetProperty(rq.cx, obj, "rright", zero);
JS_SetProperty(rq.cx, obj, "rbottom", zero);
}
else
{
JS::RootedValue zero(cx, JS::NumberValue(0));
JS_SetProperty(cx, obj, "left", zero);
JS_SetProperty(cx, obj, "top", zero);
JS_SetProperty(cx, obj, "right", zero);
JS_SetProperty(cx, obj, "bottom", zero);
JS_SetProperty(cx, obj, "rleft", zero);
JS_SetProperty(cx, obj, "rtop", zero);
JS_SetProperty(cx, obj, "rright", zero);
JS_SetProperty(cx, obj, "rbottom", zero);
JS::RootedValue zero(rq.cx, JS::NumberValue(0));
JS_SetProperty(rq.cx, obj, "left", zero);
JS_SetProperty(rq.cx, obj, "top", zero);
JS_SetProperty(rq.cx, obj, "right", zero);
JS_SetProperty(rq.cx, obj, "bottom", zero);
JS_SetProperty(rq.cx, obj, "rleft", zero);
JS_SetProperty(rq.cx, obj, "rtop", zero);
JS_SetProperty(rq.cx, obj, "rright", zero);
JS_SetProperty(rq.cx, obj, "rbottom", zero);
}
args.rval().setObject(*obj);
@@ -99,11 +100,11 @@ CStr JSI_GUISize::ToPercentString(double pix, double per)
bool JSI_GUISize::toString(JSContext* cx, uint argc, JS::Value* vp)
{
// JSAutoRequest not needed for the calls below
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
CStr buffer;
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
ScriptInterface::Request rq(*pScriptInterface);
double val, valr;
#define SIDE(side) \
@@ -120,6 +121,6 @@ bool JSI_GUISize::toString(JSContext* cx, uint argc, JS::Value* vp)
SIDE(bottom);
#undef SIDE
ScriptInterface::ToJSVal(cx, args.rval(), buffer);
ScriptInterface::ToJSVal(rq, args.rval(), buffer);
return true;
}
+39 -33
View File
@@ -52,19 +52,19 @@ void JSI_IGUIObject::RegisterScriptClass(ScriptInterface& scriptInterface)
bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
{
JSAutoRequest rq(cx);
ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface;
ScriptInterface::Request rq(*pScriptInterface);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(cx, obj, &JSI_IGUIObject::JSI_class);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(rq, obj, &JSI_IGUIObject::JSI_class);
if (!e)
return false;
JS::RootedValue idval(cx);
if (!JS_IdToValue(cx, id, &idval))
JS::RootedValue idval(rq.cx);
if (!JS_IdToValue(rq.cx, id, &idval))
return false;
std::string propName;
if (!ScriptInterface::FromJSVal(cx, idval, propName))
if (!ScriptInterface::FromJSVal(rq, idval, propName))
return false;
// Skip registered functions and inherited properties
@@ -105,7 +105,7 @@ bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
}
else if (propName == "children")
{
ScriptInterface::CreateArray(cx, vp);
ScriptInterface::CreateArray(rq, vp);
for (size_t i = 0; i < e->m_Children.size(); ++i)
pScriptInterface->SetPropertyInt(vp, i, e->m_Children[i]);
@@ -114,12 +114,12 @@ bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
}
else if (propName == "name")
{
ScriptInterface::ToJSVal(cx, vp, e->GetName());
ScriptInterface::ToJSVal(rq, vp, e->GetName());
return true;
}
else if (e->SettingExists(propName))
{
e->m_Settings[propName]->ToJSVal(cx, vp);
e->m_Settings[propName]->ToJSVal(rq, vp);
return true;
}
@@ -129,36 +129,37 @@ bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult& result)
{
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(cx, obj, &JSI_IGUIObject::JSI_class);
ScriptInterface::Request rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(rq, obj, &JSI_IGUIObject::JSI_class);
if (!e)
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
JSAutoRequest rq(cx);
JS::RootedValue idval(cx);
if (!JS_IdToValue(cx, id, &idval))
JS::RootedValue idval(rq.cx);
if (!JS_IdToValue(rq.cx, id, &idval))
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
std::string propName;
if (!ScriptInterface::FromJSVal(cx, idval, propName))
if (!ScriptInterface::FromJSVal(rq, idval, propName))
return result.fail(JSMSG_UNDEFINED_PROP);
if (propName == "name")
{
std::string value;
if (!ScriptInterface::FromJSVal(cx, vp, value))
if (!ScriptInterface::FromJSVal(rq, vp, value))
return result.fail(JSMSG_UNDEFINED_PROP);
e->SetName(value);
return result.succeed();
}
JS::RootedObject vpObj(cx);
JS::RootedObject vpObj(rq.cx);
if (vp.isObject())
vpObj = &vp.toObject();
// Use onWhatever to set event handlers
if (propName.substr(0, 2) == "on")
{
if (vp.isPrimitive() || vp.isNull() || !JS_ObjectIsFunction(cx, &vp.toObject()))
if (vp.isPrimitive() || vp.isNull() || !JS_ObjectIsFunction(rq.cx, &vp.toObject()))
{
LOGERROR("on- event-handlers must be functions");
return result.fail(JSMSG_NOT_FUNCTION);
@@ -171,7 +172,7 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
}
if (e->SettingExists(propName))
return e->m_Settings[propName]->FromJSVal(cx, vp, true) ? result.succeed() : result.fail(JSMSG_TYPE_ERR_BAD_ARGS);
return e->m_Settings[propName]->FromJSVal(rq, vp, true) ? result.succeed() : result.fail(JSMSG_TYPE_ERR_BAD_ARGS);
LOGERROR("Property '%s' does not exist!", propName.c_str());
return result.fail(JSMSG_UNDEFINED_PROP);
@@ -179,17 +180,18 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
bool JSI_IGUIObject::deleteProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::ObjectOpResult& result)
{
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(cx, obj, &JSI_IGUIObject::JSI_class);
ScriptInterface::Request rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(rq, obj, &JSI_IGUIObject::JSI_class);
if (!e)
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
JSAutoRequest rq(cx);
JS::RootedValue idval(cx);
if (!JS_IdToValue(cx, id, &idval))
JS::RootedValue idval(rq.cx);
if (!JS_IdToValue(rq.cx, id, &idval))
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
std::string propName;
if (!ScriptInterface::FromJSVal(cx, idval, propName))
if (!ScriptInterface::FromJSVal(rq, idval, propName))
return result.fail(JSMSG_UNDEFINED_PROP);
// event handlers
@@ -206,21 +208,24 @@ bool JSI_IGUIObject::deleteProperty(JSContext* cx, JS::HandleObject obj, JS::Han
bool JSI_IGUIObject::toString(JSContext* cx, uint argc, JS::Value* vp)
{
// No JSAutoRequest needed for these calls
ScriptInterface::Request rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(cx, args, &JSI_IGUIObject::JSI_class);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(rq, args, &JSI_IGUIObject::JSI_class);
if (!e)
return false;
ScriptInterface::ToJSVal(cx, args.rval(), "[GUIObject: " + e->GetName() + "]");
ScriptInterface::ToJSVal(rq, args.rval(), "[GUIObject: " + e->GetName() + "]");
return true;
}
bool JSI_IGUIObject::focus(JSContext* cx, uint argc, JS::Value* vp)
{
// No JSAutoRequest needed for these calls
ScriptInterface::Request rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(cx, args, &JSI_IGUIObject::JSI_class);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(rq, args, &JSI_IGUIObject::JSI_class);
if (!e)
return false;
@@ -231,9 +236,10 @@ bool JSI_IGUIObject::focus(JSContext* cx, uint argc, JS::Value* vp)
bool JSI_IGUIObject::blur(JSContext* cx, uint argc, JS::Value* vp)
{
// No JSAutoRequest needed for these calls
ScriptInterface::Request rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(cx, args, &JSI_IGUIObject::JSI_class);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(rq, args, &JSI_IGUIObject::JSI_class);
if (!e)
return false;
@@ -244,15 +250,15 @@ bool JSI_IGUIObject::blur(JSContext* cx, uint argc, JS::Value* vp)
bool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, JS::Value* vp)
{
JSAutoRequest rq(cx);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
ScriptInterface::Request rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(cx, args, &JSI_IGUIObject::JSI_class);
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
IGUIObject* e = ScriptInterface::GetPrivate<IGUIObject>(rq, args, &JSI_IGUIObject::JSI_class);
if (!e)
return false;
e->UpdateCachedSize();
ScriptInterface::ToJSVal(cx, args.rval(), e->m_CachedActualSize);
ScriptInterface::ToJSVal(rq, args.rval(), e->m_CachedActualSize);
return true;
}