Exact stack rooting for IGUIObject.

Refs #2415
Refs #2462

This was SVN commit r15623.
This commit is contained in:
Yves 2014-08-08 13:41:47 +00:00
parent 9872f5741f
commit 8ce8e6ba9a
4 changed files with 34 additions and 21 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2012 Wildfire Games.
/* Copyright (C) 2014 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -421,6 +421,8 @@ void IGUIObject::RegisterScriptHandler(const CStr& Action, const CStr& Code, CGU
JSContext* cx = pGUI->GetScriptInterface()->GetContext();
JSAutoRequest rq(cx);
JS::RootedValue globalVal(cx, pGUI->GetGlobalObject());
JS::RootedObject globalObj(cx, &globalVal.toObject());
const int paramCount = 1;
const char* paramNames[paramCount] = { "mouse" };
@ -433,16 +435,17 @@ void IGUIObject::RegisterScriptHandler(const CStr& Action, const CStr& Code, CGU
char buf[64];
sprintf_s(buf, ARRAY_SIZE(buf), "__eventhandler%d (%s)", x++, Action.c_str());
JSFunction* func = JS_CompileFunction(cx, JSVAL_TO_OBJECT(pGUI->GetGlobalObject()),
buf, paramCount, paramNames, Code.c_str(), Code.length(), CodeName.c_str(), 0);
JS::RootedFunction func(cx, JS_CompileFunction(cx, globalObj,
buf, paramCount, paramNames, Code.c_str(), Code.length(), CodeName.c_str(), 0));
if (!func)
return; // JS will report an error message
SetScriptHandler(Action, JS_GetFunctionObject(func));
JS::RootedObject funcObj(cx, JS_GetFunctionObject(func));
SetScriptHandler(Action, funcObj);
}
void IGUIObject::SetScriptHandler(const CStr& Action, JSObject* Function)
void IGUIObject::SetScriptHandler(const CStr& Action, JS::HandleObject Function)
{
m_ScriptHandlers[Action] = CScriptValRooted(m_pGUI->GetScriptInterface()->GetContext(), JS::ObjectValue(*Function));
}
@ -490,7 +493,7 @@ void IGUIObject::ScriptEvent(const CStr& Action)
}
}
void IGUIObject::ScriptEvent(const CStr& Action, const CScriptValRooted& Argument)
void IGUIObject::ScriptEvent(const CStr& Action, JS::HandleValue Argument)
{
std::map<CStr, CScriptValRooted>::iterator it = m_ScriptHandlers.find(Action);
if (it == m_ScriptHandlers.end())
@ -499,12 +502,13 @@ void IGUIObject::ScriptEvent(const CStr& Action, const CScriptValRooted& Argumen
JSContext* cx = m_pGUI->GetScriptInterface()->GetContext();
JSAutoRequest rq(cx);
JSObject* object = GetJSObject();
jsval arg = Argument.get();
jsval result;
bool ok = JS_CallFunctionValue(cx, object, (*it).second.get(), 1, &arg, &result);
JS::AutoValueVector paramData(cx);
paramData.append(Argument.get());
JS::RootedObject obj(cx, GetJSObject());
// TODO: Check if this temporary root can be removed after SpiderMonkey 31 upgrade
JS::RootedValue tmpScriptHandler(cx, (*it).second.get());
JS::RootedValue result(cx);
bool ok = JS_CallFunctionValue(cx, obj, tmpScriptHandler, paramData.length(), paramData.begin(), result.address());
if (!ok)
{
JS_ReportError(cx, "Errors executing script action \"%s\"", Action.c_str());

View File

@ -455,9 +455,9 @@ protected:
* @param Action Name of action
* @param Argument Argument to pass to action
*/
void ScriptEvent(const CStr& Action, const CScriptValRooted& Argument);
void ScriptEvent(const CStr& Action, JS::HandleValue Argument);
void SetScriptHandler(const CStr& Action, JSObject* Function);
void SetScriptHandler(const CStr& Action, JS::HandleObject Function);
/**
* Inputes the object that is currently hovered, this function

View File

@ -256,7 +256,7 @@ void CMiniMap::FireWorldClickEvent(int button, int clicks)
g_GUI->GetActiveGUI()->GetScriptInterface()->Eval("({})", &coords);
g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords, "x", x, false);
g_GUI->GetActiveGUI()->GetScriptInterface()->SetProperty(coords, "z", z, false);
ScriptEvent("worldclick", CScriptValRooted(cx, coords));
ScriptEvent("worldclick", coords);
UNUSED2(button);
UNUSED2(clicks);

View File

@ -334,8 +334,9 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand
return JS_FALSE;
}
JS::RootedObject vpObj(cx, &vp.toObject());
CStr eventName (CStr(propName.substr(2)).LowerCase());
e->SetScriptHandler(eventName, &vp.toObject());
e->SetScriptHandler(eventName, vpObj);
return JS_TRUE;
}
@ -628,7 +629,9 @@ JSBool JSI_IGUIObject::toString(JSContext* cx, uint argc, jsval* vp)
JSAutoRequest rq(cx);
JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp));
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return JS_FALSE;
@ -645,7 +648,9 @@ JSBool JSI_IGUIObject::focus(JSContext* cx, uint argc, jsval* vp)
JSAutoRequest rq(cx);
JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp));
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return JS_FALSE;
@ -661,7 +666,9 @@ JSBool JSI_IGUIObject::blur(JSContext* cx, uint argc, jsval* vp)
JSAutoRequest rq(cx);
JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp));
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return JS_FALSE;
@ -677,7 +684,9 @@ JSBool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, jsval* vp)
JSAutoRequest rq(cx);
JS::CallReceiver rec = JS::CallReceiverFromVp(vp);
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, JS_THIS_OBJECT(cx, vp), &JSI_IGUIObject::JSI_class, NULL);
JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp));
IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL);
if (!e)
return JS_FALSE;